实体框架6.0代码优先 - 在按主键过滤时,在简单查询中获取重复项

dan*_*oid 6 .net c# ef-code-first entity-framework-6

在我的项目中,我们使用EF Code First(v.6.0.0.0)和MS SQL Server 2012.

我已将实体框架更新到第6版.奇怪的是,在更新后的某个时刻,我开始通过主键过滤记录时获得重复的项目.

首先,我开始在以下代码中获取"Sequence包含多个元素"异常

var cateringService = context.CateringServices
                             .SingleOrDefault(x => x.Id == query.CateringServiceId)
Run Code Online (Sandbox Code Playgroud)

我检查了数据库和参数 - 这Id是一个主键,它被标记为唯一,参数是有效的.由于Id在映射中设置为主键:

this.HasKey(x => x.Id);
Run Code Online (Sandbox Code Playgroud)

我已经用FirstOrDefault代码取代了调用,并且代码运行良好.我试图使用以下代码检索谓词的所有项目:

var cateringServices = context.CateringServices
                              .Where(x => x.Id == query.CateringServiceId)
                              .ToList();
Run Code Online (Sandbox Code Playgroud)

似乎我得到了'CateringService'实体的13个实例引用了同一行.请查看附带的截图:

在此输入图像描述 在此输入图像描述

我也开始A relationship multiplicity constraint violation occurred: An EntityReference can have no more than one related object, but the query returned more than one related object.通过实体引用访问CateringService实体时获得异常.我们正在使用惰性方法并启用延迟加载.

当尝试使用Include("CateringService")Everythings 尝试访问'CateringService'时,我们不能只是替换所有SingleOrDefault调用,并且此时从项目中删除所有延迟加载用法.

请指教.

UPDATE

对不起,不太清楚.数据库中有一条与条件匹配的记录.该Id列设置为主键,因此它是唯一的.

更新2

以下是EF基于流畅映射生成的迁移代码.

CreateTable(
            "dbo.CateringServices",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false, maxLength: 200),
                    CreatedDate = c.DateTime(nullable: false),
                    CultureString = c.String(maxLength: 10),
                    AddressId = c.Int(),
                    CateringServiceGroupId = c.Int(),
                    ContactInformationId = c.Int(),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Addresses", t => t.AddressId, cascadeDelete: true)
            .ForeignKey("dbo.CateringServiceGroups", t => t.CateringServiceGroupId)
            .ForeignKey("dbo.ContactInformation", t => t.ContactInformationId, cascadeDelete: true)
            .Index(t => t.AddressId)
            .Index(t => t.CateringServiceGroupId)
            .Index(t => t.ContactInformationId);
Run Code Online (Sandbox Code Playgroud)

Ram*_*ran 2

应该使用FirstOrDefault而不是SingleOrDefault. 因为你的屏幕短与 Id cloumn 具有相同的值。所以你需要想要这个 。

否则你需要检查 id 是否是主键。并检查您的 Id 列的身份是否为 yes

因为

FirstOrDefault()

适用于输入集合中预计存在零个或多个结果,并且如果有多个结果,则调用返回第一项;如果没有,则返回默认值。

SingleOrDefault()

适用于输入集合中预计有 0 个或 1 个结果,并且如果恰好存在 1 个结果,则调用返回 1 个结果;如果没有结果,则返回默认值;如果有多个结果,则调用返回异常

并参考此 LINQ:何时使用 SingleOrDefault 与 FirstOrDefault() 和过滤条件

更新:

由于您在 Id 列尚未设置为 IDENTITY 时对数据库进行了逆向工程,因此已使用DatabaseGeneratedOption.None实体上的 Id 属性集生成了代码优先模型。

这会导致 EF 创建带有 Id 集的插入语句,该语句在将列更改为IDENTITY后不再起作用。

您必须手动修复该配置,方法是将其设置为DatabaseGeneratedOption.Identity或完全删除它,因为这是整数字段的默认值。

你需要改变

this.HasKey(e => e.Id);
   Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Run Code Online (Sandbox Code Playgroud)

更多详情

EF Code First 5.0.rc 迁移不会更新 Identity 属性

实体框架5代码优先不创建数据库

编辑:请删除旧的表值并重新生成它或删除相同的主键行。CateringServices 如果问题尚未解决,您应该需要重新生成表值:)。