簡體   English   中英

.NET核心-實體框架-急於加載Include()的意外行為

[英].NET Core - Entity Framework - Unexpected Behaviour with Eager Loading Include()

初始查詢

如果運行以下查詢, CityTranslation.IdFkLanguageNavigation得到以下結果, CityTranslation.IdFkLanguageNavigation將為null 另一方面,將填充CityTranslation.IdFkCityNavigation 考慮到它們都處於相同的層次結構級別。

    var data = await _context.City
                        .Include(x => x.CityTranslation)
                        .Include(c => c.IdFkCountryNavigation)
                        .ToListAsync();

我試過在.Include(x => x.CityTranslation) ThenInclude()之后使用ThenInclude() ,但是它不允許我使用Language屬性。


變更查詢

通過下面的查詢,我確實得到了一些意外的結果。 一旦我通過data2調試,突然我的第一個查詢結果中Language navigation屬性就被填充了!

僅當我在第二個查詢上調用ToList() ,此方法才有效,否則仍然不會被填充。 我必須假設數據是在整個EF上下文中共享的,但是如何在不向數據庫發送第二個查詢的情況下利用這種行為呢? 這種行為令我非常震驚,希望您能提供任何參考或解釋。

                var data = await _context.City
                    .Include(x => x.CityTranslation)
                    .Include(c => c.IdFkCountryNavigation).ToListAsync();

                var data2 = _context.CityTranslation.Include(c => c.IdFkLanguageNavigation).ToListAsync();

上下文

我正在使用Microsoft.EntityFrameworkCore.SqlServer版本1.1.2


public partial class City
{
    public City()
    {
        CityTranslation = new HashSet<CityTranslation>();
    }

    public int IdPkCity { get; set; }
    public string Id { get; set; }
    public string Code { get; set; }
    public string Latitude { get; set; }
    public string Longitude { get; set; }
    public string TimeZone { get; set; }
    public string Uri { get; set; }
    public string Name { get; set; }
    public string Language { get; set; }
    public int? IdFkCountry { get; set; }

    public virtual ICollection<CityTranslation> CityTranslation { get; set; }
    public virtual Country IdFkCountryNavigation { get; set; }

城市翻譯

public partial class CityTranslation
{
    public int IdPkCityTranslation { get; set; }
    public string Translation { get; set; }
    public int IdFkCity { get; set; }
    public int IdFkLanguage { get; set; }

    public virtual City IdFkCityNavigation { get; set; }
    public virtual Language IdFkLanguageNavigation { get; set; }
}

語言

public partial class Language
{
    public Language()
    {
        AirportTranslation = new HashSet<AirportTranslation>();
        CityTranslation = new HashSet<CityTranslation>();
        CountryTranslation = new HashSet<CountryTranslation>();
    }

    public int IdPkLanguage { get; set; }
    public string Name { get; set; }
    public string Code { get; set; }

    public virtual ICollection<AirportTranslation> ATranslation{ get; set; }
    public virtual ICollection<CityTranslation> CTranslation { get; set; }
    public virtual ICollection<CountryTranslation> C2Translation { get; set; }
}

這將起作用,只需粘貼此即可。

// Hits the database only once
var data = await _context.City
    .Include(x => x.CityTranslation)
        .ThenInclude(x => x.IdFkLanguageNavigation)
    .ToListAsync();

現在,關於第二個查詢為什么加載第一個查詢的“ Language導航屬性的原因,您必須研究EntityFramework的整體工作原理,並仔細閱讀顯式加載。

這是顯式加載的示例。

// Hits the database once.
var data = await _context.City
    .Include(x => x.CityTranslation)
    .ToListAsync();

var cityTranslationIds = data.Select(x => x.CityTranslation.IdPkCityTranslation);

// Hits the database the second time.
// Language navigation property will be loaded onto the data variable above
_context.Language
    .Where(x => cityTranslateIds.Contains(x.IdPkLanguage))
    .Load();

// Your second query, what you did here is essentially the same as the above's Load(), 
// but the Load() is better suited for your intention.
var data2 = await _context.CityTranslation
    .Include(c => c.IdFkLanguageNavigation)
    .ToListAsync();

根據情況,您需要在渴望加載和顯式加載之間進行選擇,以實現最佳性能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM