[英]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
:
在兩種情況下,使用ToList().Count
進行部分查詢的ToList().Count
都是錯誤的。
在兩種情況下, IQueryable<T>
擴展方法( EntityFramework
CountAsync()
和System.Core
Count()
)產生相同的結果。
項目以計數MetadataFile
是正確的
沒有 MetadataFile
的項目計數不正確
如在數據庫中驗證的, 沒有 MetadataFile
的項目數應等於8372-7908 = 464。
這表明我調用Include()
擴展方法的方式有問題。
這是由於我多次枚舉相同的查詢並且保持相同的連接嗎?
幕后是否有一些我不知道的奇怪本質,並解釋了這種看似奇怪的行為???
這就是我定義實體和映射的方式:
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.