带有SqlServer的EF7:使用复合键违反UNIQUE KEY约束

时间:2015-09-09 15:00:30

标签: sql-server entity-framework ef-code-first

我有一个表DataSourceDefinition,用于存储有关不同类型数据源的信息。由于每个数据源自然都分配了GUID,因此我将其用作主键。

每种数据源类型都有某些编号为1,2的设置...... 我想在第二个表DataSourceSettingDefinition中存储有关这些设置的信息(Name,Datatype,EditorType ...)。我认为使用由数据源类型的唯一GUID组成的复合键是自然的,后者将是外键,而Integer 1,2 ...(SettingID)在给定数据源中是唯一的类型。两者的结合总是独一无二的。

当我尝试使用以下键插入两个数据源设置定义时:

DataSourceDefinitionID - SettingID

5E880F15-80CA-45EC-AD5A-6D406B06AB08 - 1

5E880F15-80CA-45EC-AD5A-6D406B06AB08 - 2

我收到以下错误:

System.Data.SqlClient.SqlException: Violation of UNIQUE KEY 
constraint 'AK_DataSourceSettingDefinition_DataSourceDefinitionID'. Cannot 
insert duplicate key in object 'dbo.DataSourceSettingDefinition'. The 
duplicate key value is (5e880f15-80ca-45ec-ad5a-6d406b06ab08). at ...

为什么这不可能?

以下是我的代码优先模型:

public class DataSourceDefinition
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    public Guid ID { get; set; }

    [Required]
    [StringLength(50)]
    public string NameEn { get; set; }        
    [StringLength(300)]
    public string DescriptionEn { get; set; }
    ...
}

public class DataSourceSettingDefinition
{
    [Key, Column(Order = 1)]
    public Guid DataSourceDefinitionID { get; set; }

    [Key, Column(Order = 2)]
    public int SettingID { get; set; }

    [Required]
    [StringLength(50)]
    public string NameEn { get; set; }
    [StringLength(300)]
    public string DescriptionEn { get; set; }

    [Required]
    public int DataType { get; set; }
    ...
}

更新

我忘了在我的OnModelCreating中显示代码。 EF7文档的预发布版本说明

  

您仍然可以向实体类添加注释,以便其他框架(例如ASP.NET MVC)使用它们,但实体框架不会处理这些注释。

这就是为什么我将数据注释留在原地并添加以下内容

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<DataSourceSettingDefinition>().Key(m => new { m.DataSourceDefinitionID, m.SettingID });
}

2 个答案:

答案 0 :(得分:0)

事实证明,这些声明中的数据注释存在问题:

[Key, Column(Order = 1)]
public Guid DataSourceDefinitionID { get; set; }

[Key, Column(Order = 2)]
public int SettingID { get; set; }

如果我删除数据注释并将主键构建单独保留在流畅的API中,它将按预期工作。尽管预发布文档说EF7不会处理数据注释,但仍然存在副作用。有了数据注释,似乎生成了主键和备用键,但不是复合键。在这种情况下,插入两个具有相同GUID的DataSourceSettingDefinition当然必须失败。

答案 1 :(得分:0)

在EF 7中

无法使用数据注释配置唯一约束。您必须使用流畅的API来配置它。

如何配置

class MyContext : DbContext
{
    public DbSet<Employee> Employees { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Employee>()
            .HasAlternateKey(e => e.EmployeeCode)
            .HasName("AlteranteKey_EmployeeCode");
    }
}

class Employee
{
    [Key]
    public int EmployeeId { get; set; }
    public string Name { get; set; }
    public string EmployeeCode { get; set; }
    public DateTime DateOfBirth { get; set; }
}