繁体   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