我使用实体框架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
有办法吗?
对于那些在寻找2021年解决方案的人来说,公认答案的工作版本现在应该是这样的:
[Index(nameof(FirstColumn), nameof(SecondColumn), IsUnique = true)]
public class Entity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string EntityId { get; set;}
public int FirstColumn { get; set;}
public int SecondColumn { get; set;}
}
因此,注释应该存在于模型上,而不是单独的列上。还要注意nameof()语法。
这个答案来自于官方文档:https://learn.microsoft.com/en-us/ef/core/modeling/indexes?tabs=data-annotations
在@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; }
}
我假设您总是希望EntityId是主键,所以用复合键代替它是不可取的(如果仅仅是因为复合键的使用要复杂得多,并且主键在业务逻辑中也有意义是不明智的)。
您至少应该在数据库中的两个字段上创建一个唯一键,并在保存更改时专门检查是否存在违反唯一键的异常。
此外,您可以(应该)在保存更改之前检查惟一值。最好的方法是使用Any()查询,因为它可以最小化传输的数据量:
if (context.Entities.Any(e => e.FirstColumn == value1
&& e.SecondColumn == value2))
{
// deal with duplicate values here.
}
请注意,单凭这张支票是远远不够的。在检查和实际提交之间总是有一些延迟,所以你总是需要唯一的约束+异常处理。