我使用实体框架5.0代码第一;

public class Entity
 {
   [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public string EntityId { get; set;}
   public int FirstColumn  { get; set;}
   public int SecondColumn  { get; set;}
 }

我想让FirstColumn和SecondColumn的组合是唯一的。

例子:

Id  FirstColumn  SecondColumn 
1       1              1       = OK
2       2              1       = OK
3       3              3       = OK
5       3              1       = THIS OK 
4       3              3       = GRRRRR! HERE ERROR

有办法吗?


当前回答

您需要定义一个复合键。

使用数据注释,它看起来像这样:

public class Entity
 {
   public string EntityId { get; set;}
   [Key]
   [Column(Order=0)]
   public int FirstColumn  { get; set;}
   [Key]
   [Column(Order=1)]
   public int SecondColumn  { get; set;}
 }

你也可以在覆盖onmodelcreation时通过指定modelBuilder来做到这一点:

modelBuilder.Entity<Entity>().HasKey(x => new { x.FirstColumn, x.SecondColumn });

其他回答

您需要定义一个复合键。

使用数据注释,它看起来像这样:

public class Entity
 {
   public string EntityId { get; set;}
   [Key]
   [Column(Order=0)]
   public int FirstColumn  { get; set;}
   [Key]
   [Column(Order=1)]
   public int SecondColumn  { get; set;}
 }

你也可以在覆盖onmodelcreation时通过指定modelBuilder来做到这一点:

modelBuilder.Entity<Entity>().HasKey(x => new { x.FirstColumn, x.SecondColumn });

我想补充我的答案,因为提供的解决方案对我没有帮助。在我的例子中,其中一列是外键引用。

旧的模型:

public class Matrix
{
    public int ID { get; set; }

    public MachineData MachineData { get; set; }

    public MachineVariant MachineVariant { get; set; }
}

注意,MachineVariant是一个enum, MachineData是一个引用。

尝试使用@Bassam Alugili提供的解决方案:

modelBuilder.Entity<Matrix>()
   .HasIndex(sm => new { sm.MachineData, sm.DoughVariant }).IsUnique(true);

没有工作。所以我为machineData外键添加了一个ID列,如下所示:

public class Matrix
{
    public int ID { get; set; }

    public MachineData MachineData { get; set; }

    [ForeignKey("MachineData")]
    public int MachineDataID { get; set; }

    public MachineVariant MachineVariant { get; set; }
}

并将模型构建器代码更改为:

modelBuilder.Entity<Matrix>()
   .HasIndex(sm => new { sm.MachineDataID, sm.DoughVariant }).IsUnique(true);

哪一种方法得到了想要的解决方案

最近添加了一个组合键的唯一性2列使用'chuck'推荐的方法,谢谢@chuck。只有这条路在我看来比较干净:

public int groupId {get; set;}

[Index("IX_ClientGrouping", 1, IsUnique = true)]
public int ClientId { get; set; }

[Index("IX_ClientGrouping", 2, IsUnique = true)]
public int GroupName { get; set; }

我假设您总是希望EntityId是主键,所以用复合键代替它是不可取的(如果仅仅是因为复合键的使用要复杂得多,并且主键在业务逻辑中也有意义是不明智的)。

您至少应该在数据库中的两个字段上创建一个唯一键,并在保存更改时专门检查是否存在违反唯一键的异常。

此外,您可以(应该)在保存更改之前检查惟一值。最好的方法是使用Any()查询,因为它可以最小化传输的数据量:

if (context.Entities.Any(e => e.FirstColumn == value1 
                           && e.SecondColumn == value2))
{
    // deal with duplicate values here.
}

请注意,单凭这张支票是远远不够的。在检查和实际提交之间总是有一些延迟,所以你总是需要唯一的约束+异常处理。

在@chuck接受的回答中,有一条评论说它在FK的情况下不起作用。

它为我工作,ef6.net4.7.2的情况下

public class OnCallDay
{
     public int Id { get; set; }
    //[Key]
    [Index("IX_OnCallDateEmployee", 1, IsUnique = true)]
    public DateTime Date { get; set; }
    [ForeignKey("Employee")]
    [Index("IX_OnCallDateEmployee", 2, IsUnique = true)]
    public string EmployeeId { get; set; }
    public virtual ApplicationUser Employee{ get; set; }
}