配置为一对一关系的EF 6有时会违反约束

时间:2018-04-12 13:57:48

标签: c# sql-server entity-framework entity-framework-6

我在EF 6.1.3中使用Fluent API来定义实体User和实体EcommerceCart之间的一对一关系。 99.9%的时间似乎一切正常,但偶尔我们的异常记录器告诉我们,在尝试访问User.Cart时会抛出以下异常:

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.

我们检查了数据库,尽管实体类型之间存在一对一的关系,但实体框架似乎设法为同一个用户创建了2个购物车。

最令我印象深刻的是,创建实体时异常永远不会发生,但是当代码尝试访问User.Cart时,会在数据库中找到多个结果。

知道如何发生这种情况?

PS:我正在使用延迟加载,但我不认为这会产生影响。

这些是我的实体:

public class User
{
    public Guid Id { get; set; }
    public virtual EcommerceCart Cart{ get; set; }
}

public class EcommerceCart
{
    public Guid Id { get; set; }
    public virtual User User { get; set; }
}

这些是我的配置文件:

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        HasKey(x => x.Id);
        Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
        HasOptional(x => x.Cart).WithOptionalPrincipal(y => y.User).Map(x => x.MapKey("User_Id"));
    }
}

public class EcommerceCartConfiguration : EntityTypeConfiguration<EcommerceCart>
{
    public EcommerceCartConfiguration()
    {
        HasKey(a => a.Id);
        Property(a => a.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired();
    }
}

这就是EcommerceCarts表的样子:

enter image description here

1 个答案:

答案 0 :(得分:1)

根据adam0101建议,我创建了以下迁移,强制执行  外键User_Id是唯一的:

public partial class EcommerceCart_User_Index : DbMigration
{
    public override void Up()
    {
        DropIndex("dbo.EcommerceCarts", new[] { "User_Id" });
        Sql(
            @"CREATE UNIQUE NONCLUSTERED INDEX IX_User_Id
            ON dbo.EcommerceCarts(User_Id)
            WHERE User_Id IS NOT NULL");
    }
}

不幸的是,我无法使用Fluent API找到任何其他解决方案,因为似乎无法在不使用SQL的情况下在Navigation属性上创建唯一索引。

如果有人知道更好的解决方案,请告诉我。