كيف يمكنني الاستعلام الهرمية مع LinqToSQL?
-
19-08-2019 - |
سؤال
لدي التسلسل الهرمي الذي أود الاستعلام مع LinqToSql:
البلد -> المنطقة -> المدينة> الرمز البريدي
كل كيان يحمل كل إشارة إلى أنه الأصل (على سبيل المثال.المنطقة.البلد) و مجموعة من الأطفال (على سبيل المثال.المنطقة.المدن).
أود حريصة تحميل كل كيان الأم جنبا إلى جنب مع البلدان والمناطق ولكن تحميل كسول المدن رموز البريدي.
إلى تعقيد الأمور ، كل كيان يجري مترجمة قبل عرضها في النموذج.ذلك البلد.اسم تغييرات على أساس اللغة.
وهنا بعض مقتطفات من ما لدي حتى الآن:
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);
}
فشل الاختبار مع:
النظام.NotSupportedException:الأسلوب 'النظام.Linq.IQueryable`1[الخط المباشر.EducationCompass.نموذج.المنطقة] GetRegions(Int32)' لا يوجد لديه دعم الترجمة إلى SQL.
كيف تنصحين اذهب عن هذا ؟ سيكون أبسط (أو ممكن) لو كل مستوى من التسلسل الهرمي في نفس الجدول بدلا من فصل واحد ؟
المحلول
كنت تريد الذهاب إلى استخدام linq مصمم على اقامة علاقات بين الأشياء الخاصة بك.هذا يحصل لك الخروج من كتابة الانضمام بعد الانضمام بعد الانضمام من خلال خلق خصائص.
- بين بلد و المناطق
- بين المنطقة ومدنها
- بين بلد و لها تعريب
- بين منطقة و لها تعريب
كنت تريد الذهاب إلى استخدام ToList للتفريق تلك العمليات كنت تنوي أن تترجم إلى SQL ، تلك العمليات التي كنت تنوي القيام به في الكود المحلي.إذا كنت لا تفعل هذا, سوف نستمر في رؤية تلك "لا يمكن ترجمة الأسلوب في SQL" استثناءات.
أنت أيضا تريد الذهاب إلى استخدام 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();
}
}
نصائح أخرى
وهذا هو قطعة لزجة واحد من التعليمات البرمجية، وأنا لن قد أجبت على هذا يرجع إلى عدم وجود المهارات ذات الصلة إذا كان أي شخص آخر، ولكن منذ كان لديك أي ردود ...
واستطيع ان اقول لكم ماذا تعني رسالة الخطأ. وهذا يعني لا يمكن أن تترجم GetRegions وظيفة إلى مزود من قبل LINQ إلى SQL موفر. ويمكن لبعض وظائف المدمج في أن يكون، لأن مزود يفهمها، وهنا ل قائمة . وإلا فإنك يمكن أن توفر ترجمة ترى هنا .
في حالتك تحتاج إلى "المضمنة" منطق هذا الاستعلام، فإن المنطق لا يعبرون الحدود من استدعاء دالة، لأنك تتعامل مع شجرة التعبير، ومزود خدمة لا يمكن الاتصال مرة أخرى إلى حسابك طريقة GetRegions.
وأما بالنسبة للطريقة الصحيحة للقيام بذلك، سيكون لديك ليكون الذهاب، وأنا لم يكن لديك الوقت ليجبر أنت في هذه اللحظة. (ما لم يكن شخص آخر لديه الوقت والمهارة؟)
وحظا سعيدا.