2013-12-12 36 views
6

在我的项目中,我们使用的是EF代码第一次(v.6.0.0.0)和MS SQL Server 2012的实体框架6.0代码第一 - 按主键

我在过滤时在一个简单的查询得到复制项目已经更新到实体框架第6版。 奇怪的是,在更新后的某个时候,我开始获取重复的项目,同时通过主键过滤记录。

首先,我开始得到“序列包含多个元素”在下面的代码

var cateringService = context.CateringServices 
          .SingleOrDefault(x => x.Id == query.CateringServiceId) 

我检查了数据库和参数例外 - 该Id主键 ,它被标记为唯一,并且该参数是有效的。作为Id设定为在映射主键:

this.HasKey(x => x.Id); 

我已经取代了电话与FirstOrDefault和代码运行良好。 我试着检索所有正在使用下面的代码mathing谓词的项目:

var cateringServices = context.CateringServices 
           .Where(x => x.Id == query.CateringServiceId) 
           .ToList(); 

看来,我得到了“CateringService”实体的13个实例引用同一行。请看附截图:

enter image description here enter image description here

除了我已经开始得到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")访问'CateringService'时,所有的操作都很好,但我们不能只替换所有的SingleOrDefault调用,并且在此时删除项目中的所有惰性加载用法。

请指教。

UPDATE

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

UPDATE 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); 
+0

你的代码中'query'的定义是什么? ('x.Id == query.CateringServiceId') –

+0

它是一个非常简单的类的实例 - 只有一个属性'public Int32 CateringServiceId {get;组; }' – danyloid

+0

但我试过使用硬编码值,例如'x => x.Id == 1'。或数据库中的任何其他现有ID。仍然得到相同的结果。 – danyloid

回答

2

应该使用FirstOrDefault而不是SingleOrDefault。因为你的屏幕短期有编号cloumn.So你需要想这个相同的值。

否则你需要检查id是否是主键。和检查组是身份是你的ID列

因为

FirstOrDefault()

是当零个或多个结果预计将存在于输入采集和调用返回如果有多个结果,则为第一个项目,如果没有,则为Default。

的SingleOrDefault()

是当零个或一个结果输入集合在预计为,如果恰好一个结果是本呼叫返回一个结果,默认如果没有结果和异常,如果超过一个结果

,并指这LINQ: When to use SingleOrDefault vs. FirstOrDefault() with filtering criteria

更新时间:

既然你逆向工程数据库时,ID列未设置身份然而,代码首款车型已经与DatabaseGeneratedOption.None集的生成实体上的Id属性。

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

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

您需要更改

this.HasKey(e => e.Id); 
    Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

更多deatisls

EF Code First 5.0.rc Migrations doesn`t update Identity property

Entity Framework 5 code-first not creating database

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

+0

对。但是如果你已经读过这个问题的标题,你可能已经注意到,在FirstOrDefault应该被使用的情况下,情况并非如此。 但问题是,应该有一个单一的记录。就像在数据库中一样。 而且无论如何,你的答案并没有解决'A关系多重性约束违反发生'错误的问题。 – danyloid

+0

是的,但你的屏幕短有相同的价值为Id cloumn.So你需要这个 –

+0

对。这就是我所问的。我已经说过,ID在数据库中是唯一的。 – danyloid

0

您可以使用.Top(1)而不是.FirstOrDefault()或.SingleOrDefault()。

我是Linq的新手,但据我所知top()将只返回指定的行数。我不知道FirstOrDefault和SingleOrDefault。

+0

其实你应该使用FirstOrDefault,否则top(1)仍然返回一个IEnumberable。 如果存在_any_或返回null,则FirstOrDefault()将返回序列中的第一个项目 如果没有项目,则SingleOrDefault将返回null,如果项目中有一个(且仅有一个),则返回null,如果有多个项目 – finman