首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用EF + LINQ: Include(.).Where(.)

使用EF + LINQ: Include(.).Where(.)
EN

Stack Overflow用户
提问于 2014-07-25 21:05:30
回答 2查看 334关注 0票数 1

我正在经历一场噩梦,弄清楚为什么下面的Include(...)Where(...)的组合没有产生预期的结果:

  • 我通过Where(...)将项目从数据库中分离成两部分。
  • Where(...)条件是相互排斥和互补的。
  • Where(...)调用依赖于相关对象,因此我使用Include(...)
  • 我知道这两个部分都包含元素。

代码:

代码语言:javascript
运行
复制
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);
}

打印的输出如下:

代码语言:javascript
运行
复制
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的部分查询的计数都是错误的。
  2. IQueryable<T>扩展方法(来自EntityFrameworkCountAsync()和来自System.CoreCount() )在两种情况下都得到了相同的结果。

代码语言:javascript
运行
复制
- The count of items **with** a `MetadataFile` is **correct**
- The count of items **without** a `MetadataFile` is **incorrect**

  1. 在数据库中验证的不带a MetadataFile的项的计数应该等于8372-7908= 464。

这表明我调用Include()扩展方法的方式有问题。

  • 这是因为我多次枚举相同的查询,并且保持相同的连接吗?
  • 是否有什么奇怪的性质背后,我没有意识到,并解释了这个看似怪异的行为?

请放点光!

EF模型细节

我就是这样定义实体和映射的:

代码语言:javascript
运行
复制
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; }
    ...
}

以及映射:

代码语言:javascript
运行
复制
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关系的效果。

代码语言:javascript
运行
复制
FeedEntry 1 ←—→ 0..1 MetadataFile

其中FeedEntry自动是关系中的主体,MetadataFile是依赖者。

所以这个问题已经得到了回答,解释就像answer below描述的那样,以及我使用描述的模型同时针对一个新的数据库和一个现有的数据库的事实。

EN

Stack Overflow用户

回答已采纳

发布于 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并返回整数计数结果,而不需要对象模型映射)。

票数 1
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24964493

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档