我正在经历一场噩梦,弄清楚为什么下面的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
的部分查询的计数都是错误的。IQueryable<T>
扩展方法(来自EntityFramework
的CountAsync()
和来自System.Core
的Count()
)在两种情况下都得到了相同的结果。- The count of items **with** a `MetadataFile` is **correct**
- The count of items **without** a `MetadataFile` is **incorrect**
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
是依赖者。
所以这个问题已经得到了回答,解释就像answer below描述的那样,以及我使用描述的模型同时针对一个新的数据库和一个现有的数据库的事实。
发布于 2014-07-26 06:58:49
实体框架不以这种方式支持1:1或1:0..1关系。只有当存在公共共享主键时,它才支持它们。这意味着两个表必须具有相同的主键名,一个PK必须是另一个PK的外键(这也意味着至少一个PK不能是标识字段)
原因是EF不支持唯一的约束,因此不能保证在外键字段中没有重复的id。
从技术上讲,EF6.1支持唯一的索引,但是它们还没有增强EF以允许使用它来使1:1的关系工作。
EF根本不支持这种映射,虽然它在某些场景中似乎有效,但是您会遇到这样的奇怪和奇怪的行为,并且无法信任它。
ToList()方法不能工作的原因是ToList()方法实际上需要映射和检索对象。这导致了一个混乱的模型。虽然非ToList()版本只执行计数而不实际映射任何对象(它只是生成sql并返回整数计数结果,而不需要对象模型映射)。
https://stackoverflow.com/questions/24964493
复制相似问题