簡體   English   中英

使用EF + LINQ的奇怪行為:Include(…).Where(…)

[英]Strange behaviour using EF + LINQ: Include(…).Where(…)

我有點惡夢,想知道為什么下面的Include(...)Where(...)不能產生預期結果的原因:

  • 我通過Where(...)將數據庫中的項目分為兩部分。
  • Where(...)條件是互斥和互補的。
  • Where(...)調用取決於相關對象,因此我使用Include(...)
  • 我知道兩個部分都包含元素。

碼:

using (var db = new FeedDbContext("My-Database-Connection"))
{
    var queryWithout = db.FeedEntries
                         .Include(f => f.MetadataFile)
                         .Where(f => f.MetadataFile == null);
    var queryWith    = db.FeedEntries
                         .Include(f => f.MetadataFile)
                         .Where(f => f.MetadataFile != null);

    //-- using ToList().Count
    var totalCount   = db.FeedEntries.ToList().Count;
    var countWithout = queryWithout.ToList().Count;
    var countWith    = queryWith.ToList().Count;

    Console.WriteLine("totalCount using ToList().Count: {0}", totalCount);
    Console.WriteLine("countWithout using ToList().Count: {0}", countWithout);
    Console.WriteLine("countWith using ToList().Count: {0}", countWith);

    //-- using Count()
    totalCount   = db.FeedEntries.Count();
    countWithout = queryWithout.Count();
    countWith    = queryWith.Count();

    Console.WriteLine("totalCount using Count(): {0}", totalCount);
    Console.WriteLine("countWithout using Count(): {0}", countWithout);
    Console.WriteLine("countWith using Count(): {0}", countWith);

    //-- using CountAsync()
    totalCount   = await db.FeedEntries.CountAsync();
    countWithout = await queryWithout.CountAsync();
    countWith    = await queryWith.CountAsync();

    Console.WriteLine("totalCount using CountAsync(): {0}", totalCount);
    Console.WriteLine("countWithout using CountAsync(): {0}", countWithout);
    Console.WriteLine("countWith using CountAsync(): {0}", countWith);
}

打印的輸出為:

totalCount using ToList().Count: 8372
countWithout using ToList().Count: 8372
countWith using ToList().Count: 0

totalCount using Count(): 8372
countWithout using Count(): 8372
countWith using Count(): 7908

totalCount using CountAsync(): 8372
countWithout using CountAsync(): 8372
countWith using CountAsync(): 7908

除了totalCount

  1. 在兩種情況下,使用ToList().Count進行部分查詢的ToList().Count都是錯誤的。

  2. 在兩種情況下, IQueryable<T>擴展方法( EntityFramework CountAsync()System.Core Count() )產生相同的結果。

    • 項目計數MetadataFile正確的

    • 沒有 MetadataFile的項目計數不正確

  3. 如在數據庫中驗證的, 沒有 MetadataFile的項目數應等於8372-7908 = 464。

這表明我調用Include()擴展方法的方式有問題。

  • 這是由於我多次枚舉相同的查詢並且保持相同的連接嗎?

  • 幕后是否有一些我不知道的奇怪本質,並解釋了這種看似奇怪的行為???

請說明一下!!!


EF型號詳情

這就是我定義實體和映射的方式:

public partial class FeedEntry
{
    public int Id { get; set; }
    ...
    public virtual MetadataFile MetadataFile { get; set; }
    public virtual ICollection<ImageFile> ImageFiles { get; set; }
    public virtual ICollection<VideoFile> VideoFiles { get; set; }
    ...
}

public partial class MetadataFile : FileBase
{
    ...
    public virtual FeedEntry FeedEntry { get; set; }
    ...
}

和映射:

modelBuilder.Entity<FeedEntry>()
            .HasOptional(t => t.MetadataFile)
            .WithRequired(t => t.FeedEntry);
modelBuilder.Entity<FeedEntry>()
            .HasMany(t => t.ImageFiles)
            .WithRequired(t => t.FeedEntry);
modelBuilder.Entity<FeedEntry>()
            .HasMany(t => t.VideoFiles)
            .WithRequired(t => t.FeedEntry);

特別是,這具有定義Optional:Required關系的效果

FeedEntry 1 ←—→ 0..1 MetadataFile

其中, FeedEntry自動是關系中的主體, MetadataFile是依賴項。


因此,該問題已得到解答,其解釋全如以下答案所述 ,事實是我正在使用所描述的模型同時針對新數據庫和現有數據庫。

實體框架不以這種方式支持1:1或1:0..1關系。 僅在存在公共共享主鍵時才支持它們。 這意味着兩個表必須具有相同的主鍵名稱,並且一個PK必須是另一個PK的外鍵(這也意味着至少一個PK不能是IDENTITY字段)

這樣做的原因是EF不支持唯一約束,因此它不能保證外鍵字段中沒有重復的ID。

從技術上講,EF6.1支持唯一索引,但是它們尚未增強EF,以使其能夠用於使1:1關系正常工作。

EF根本不支持這種映射,盡管它在某些情況下似乎可以使用,但您將遇到這種奇怪而怪異的行為,並且無法信任它。

ToList()方法不起作用,而其他方法起作用的原因是,ToList()方法實際上需要映射對象並檢索它們。 這導致模型混亂。 盡管non-ToList()版本僅執行計數而沒有實際映射任何對象(它僅生成sql並返回整數計數結果,所以不需要對象模型映射)。

嘗試兩件事,第一件事必須做EF如何加載數據。

我認為它認為由於延遲加載而不需要MetadataFile ,因此請關閉它,看看它是否有任何改變:

db.ContextOptions.LazyLoadingEnabled = false;

還請嘗試使用成員.Include("MetadataFile").的字符串文字.Include("MetadataFile"). 這可能是關鍵。

暫無
暫無

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

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