2

LinqToSqlでクエリしたい階層があります。

国->地域->都市->郵便番号

各エンティティは、その親(Region.Countryなど)への参照と子のコレクション(Region.Citiesなど)の両方を保持します。

国と地域とともに各エンティティの親を積極的にロードしたいのですが、都市と郵便番号を遅延ロードします。

複雑なことに、各エンティティはモデルに投影される前にローカライズされています。したがって、Country.Nameは言語に基づいて変更されます。

これが私がこれまでに持っているもののいくつかの断片です:

public IQueryable<Country> ListCountries()
{
  return ProjectCountry(dataContext.GetTable<ec_Country>());
}

private IQueryable<Country> ProjectCountry(IQueryable<ec_Country> query)
{
  var result = from country in query
  join localized in dataContext.GetTable<ec_CountryLocalization>() on country.CountryID equals localized.CountryID
  let regions = GetRegions(country.CountryID)
  where localized.StatusID == 4 && localized.WebSiteID == this.webSiteID
  select new Country(country.CountryID) {
    CreatedDate = country.CreatedDate,
    IsDeleted = country.IsDeleted,
    IsoCode = country.IsoCode,
    Name = country.Name,
    Regions = new LazyList<Region>(regions),
    Text = localized.Text,
    Title = localized.Title,
    UrlKey = country.UrlKey
  };

  return result;
}

private IQueryable<Region> GetRegions(Int32 countryID)
{
  var query = from r in dataContext.GetTable<ec_Region>()
  where r.CountryID == countryID
  orderby r.Name
  select r;

  return ProjectRegion(query);
}

private IQueryable<Region> ProjectRegion(IQueryable<ec_Region> query)
{
  var result = from region in query
  join localized in dataContext.GetTable<ec_RegionLocalization>() on region.RegionID equals localized.RegionID
  join country in ListCountries() on region.CountryID equals country.CountryID
  let cities = GetCities(region.RegionID)
  select new Region(region.RegionID) {
    Cities = new LazyList<City>(cities),
    Country = country,
    CountryID = region.CountryID,
    CreatedDate = region.CreatedDate,
    IsDeleted = region.IsDeleted,
    IsoCode = region.IsoCode,
    Name = region.Name,
    Text = localized.Text,
    Title = localized.Title,
    UrlKey = region.UrlKey
  };

  return result;
}

...など。

[TestMethod]
public void DataProvider_Correctly_Projects_Country_Spike()
{
  // Act
  Country country = dataProvider.GetCountry(1);

  // Assert
  Assert.IsNotNull(country);
  Assert.IsFalse(String.IsNullOrEmpty(country.Description));
  Assert.IsTrue(country.Regions.Count > 0);
}

テストは次のように失敗します:

System.NotSupportedException:メソッド'System.Linq.IQueryable`1 [Beeline.EducationCompass.Model.Region] GetRegions(Int32)'には、SQLへのサポートされた変換がありません。

私がこれについて行くことをどのように勧めますか?階層の各レベルが別々のテーブルではなく同じテーブルにある場合、それはより単純(または可能)でしょうか?

4

2 に答える 2

1

これは厄介なコードの 1 つです。他の誰かが持っていたとしても、関連するスキルがないため、私はこれに答えなかったでしょうが、あなたには応答がなかったので...

エラーメッセージの意味を教えてください。これは、関数 GetRegions が linq to sql プロバイダーによって sql に変換できないことを意味します。一部の組み込み関数は、プロバイダーがそれらを理解しているため、次のリストにある可能性があります。それ以外の場合は、翻訳を提供できますこちらを参照してください。

あなたの状況では、このクエリのロジックを「インライン化」する必要があります。式ツリーを扱っているため、ロジックは関数呼び出しの境界を越えません。SQL サーバーは GetRegions メソッドにコールバックできません。

それを行う正確な方法については、試してみる必要があります。現時点では、あなたに義務付ける時間はありません。(他の誰かが時間とスキルを持っていない限り?)

幸運を。

于 2009-01-21T00:31:47.823 に答える