質問

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

国-<!> gt;地域-<!> gt;市-<!> gt; ZipCode

各エンティティは、その親への参照(例: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への変換がサポートされていません。

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

役に立ちましたか?

解決

linqデザイナーを使用して、オブジェクト間の関係を設定します。これにより、プロパティを作成することにより、結合後の結合を記述する必要がなくなります。

  • 国とその地域の間
  • 地域とその都市の間
  • 国とそのローカリゼーションの間
  • 地域とそのローカリゼーションの間

ToList を使用して分離しますSQLに変換する予定の操作、およびローカルコードで行う予定の操作。これを行わないと、これらの<!> quot;メソッドをSQL <!> quotに変換できません。例外。

を使用することもできます。 DataLoadOptions を使用して、場合によってはこれらのプロパティを積極的に読み込みます。ここに私の刺し傷があります。

DataLoadOptions dlo = new DataLoadOptions();
//bring in the Regions for each Country
dlo.LoadWith<ec_Country>(c => c.Regions);
//bring in the localizations
dlo.AssociateWith<ec_Country>(c => c.Localizations
  .Where(loc => loc.StatusID == 4 && loc.WebSiteID == this.webSiteID)
);
dlo.AssociateWith<ec_Region>(r => r.Localizations);

//set up the dataloadoptions to eagerly load the above.
dataContext.DataLoadOptions = dlo;

//Pull countries and all eagerly loaded data into memory.
List<ec_Country> queryResult = query.ToList();

//further map these data types to business types
List<Country> result = queryResult
  .Select(c => ToCountry(c))
  .ToList();

public Country ToCountry(ec_Country c)
{
  return new Country()
  {
    Name = c.Name,
    Text = c.Localizations.Single().Text,
    Regions = c.Regions().Select(r => ToRegion(r)).ToList()
  }
}

public Region ToRegion(ec_Region r)
{
  return new Region()
  {
    Name = r.Name,
    Text = r.Localizations.Single().Text,
    Cities = r.Cities.Select(city => ToCity(city)).ToLazyList();
  }
}

他のヒント

これは1つのスティッキーなコードです。他に誰かが持っていたとしても、関連するスキルが不足しているため、これには答えませんでしたが、あなたには応答がなかったので...

エラーメッセージの意味を説明できます。これは、関数GetRegionsがlinq to sqlプロバイダーによってsqlに変換できないことを意味します。いくつかの組み込み関数は、プロバイダーがそれらを理解しているため、リストです。 。それ以外の場合は、こちらをご覧ください。

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

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

がんばって。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top