EF6 codefirst 中的唯一多列

Posted

技术标签:

【中文标题】EF6 codefirst 中的唯一多列【英文标题】:Unique multiple column in EF6 codefirst 【发布时间】:2014-12-13 11:35:45 【问题描述】:

我的班级电子邮件看起来像:

public class Email

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id  get; set; 
    public string Subject  get; set; 
    public string Body  get; set; 
    public string From  get; set; 
    public DateTime SentOn  get; set; 
    public List<string> To  get; set; 

为了确保唯一性,我在 SubjectFromSentOn 上创建了一个复合键

这产生了当主题超过 128 个字符时,验证失败的问题。所以我只是在上面放了一个[MaxLength] 属性。但是现在它不能是关键列

我该怎么办?有没有办法在不成为密钥的情况下确保唯一性?

【问题讨论】:

我可以发送两封相同主题的不同电子邮件。如果SentOn 具有毫秒精度,那么FromSentOn 就足够了。 而且 From 不应该是 NVarChar(MAX) 【参考方案1】:

如果您使用EF 6.1,您可以使用Multiple-Column Indexes 功能:

public class Email

   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int Id  get; set; 
   [Index("IX_EmailUniqueness", 1, IsUnique = true)]
   public string Subject  get; set; 
   public string Body  get; set; 
   [Index("IX_EmailUniqueness", 2, IsUnique = true)]
   public string From  get; set; 
   [Index("IX_EmailUniqueness", 3, IsUnique = true)]
   public DateTime SentOn  get; set; 
   public List<string> To  get; set; 

【讨论】:

在我的情况下也是如此,但是当我生成初始配置(添加迁移)时,迁移的 Up() 方法仅为第一列生成索引:.Index(t => t.XXXXX,唯一=真,名称:“ÏX_XXXX”) 当我对作为字符串的属性/列执行此操作时,EF 给出以下错误:表 'dbo.Patients' 中的列 'Email' 的类型无法用作索引中的键列。【参考方案2】:

在此处查看此 SO 帖子,您可以添加索引以确保唯一性,作为属性或使用 EF FluentAPI Setting unique Constraint with fluent API?

请注意,您必须使用 EF6.1 或更高版本。这是MSDN article

编辑:

在检查了here 和 msdn 之后,看起来 PK 和索引键的限制为 900 字节或更少,因此您需要使用您的身份作为键,并以另一种方式确保唯一性.

例如,我尝试手动将主题列创建为唯一长度为 4000 的列,但出现此错误:

Warning! The maximum key length is 900 bytes. The index 'UQ__Emails__A2B1D9048E9A2A16' has maximum length of 8000 bytes. For some combination of large values, the insert/update operation will fail. 如果您要执行集群键选项,您会在创建时收到此警告(我在每列上设置了 4000 的长度)Warning! The maximum key length is 900 bytes. The index 'PK_dbo.Emails' has maximum length of 16012 bytes. For some combination of large values, the insert/update operation will fail. 这实际上意味着几乎所有现实世界的条目都会失败。

因此,虽然您可以手动绕过 128 长度限制,但不建议这样做,您很可能会遇到错误和丢失数据。并且 EF 只会让您拥有 128 的密钥长度 - 不确定如果您落后并更改它会做什么。

【讨论】:

它仍然抱怨不能成为关键栏:( 确保唯一性的一个选项是获取您想要保持唯一性的属性的哈希并将其用作唯一列 - 或者(性能较差)在存储之前检查集合。跨度>

以上是关于EF6 codefirst 中的唯一多列的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework 6 Code First 方法 - 唯一约束不起作用

EF Codefirst 验证唯一属性?

需要根据表中的唯一值将一列分解为多列?

将房间数据库中的唯一约束添加到多列

如何在EF CodeFirst中使用唯一约束

pandas df中多列的唯一记录计数