我使用实体框架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
有办法吗?
如果你使用Code-First,你可以实现一个自定义扩展HasUniqueIndexAnnotation
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Infrastructure.Annotations;
using System.Data.Entity.ModelConfiguration.Configuration;
internal static class TypeConfigurationExtensions
{
public static PrimitivePropertyConfiguration HasUniqueIndexAnnotation(
this PrimitivePropertyConfiguration property,
string indexName,
int columnOrder)
{
var indexAttribute = new IndexAttribute(indexName, columnOrder) { IsUnique = true };
var indexAnnotation = new IndexAnnotation(indexAttribute);
return property.HasColumnAnnotation(IndexAnnotation.AnnotationName, indexAnnotation);
}
}
然后像这样使用它:
this.Property(t => t.Email)
.HasColumnName("Email")
.HasMaxLength(250)
.IsRequired()
.HasUniqueIndexAnnotation("UQ_User_EmailPerApplication", 0);
this.Property(t => t.ApplicationId)
.HasColumnName("ApplicationId")
.HasUniqueIndexAnnotation("UQ_User_EmailPerApplication", 1);
这将导致以下迁移:
public override void Up()
{
CreateIndex("dbo.User", new[] { "Email", "ApplicationId" }, unique: true, name: "UQ_User_EmailPerApplication");
}
public override void Down()
{
DropIndex("dbo.User", "UQ_User_EmailPerApplication");
}
最终在数据库中是:
CREATE UNIQUE NONCLUSTERED INDEX [UQ_User_EmailPerApplication] ON [dbo].[User]
(
[Email] ASC,
[ApplicationId] ASC
)
我假设您总是希望EntityId是主键,所以用复合键代替它是不可取的(如果仅仅是因为复合键的使用要复杂得多,并且主键在业务逻辑中也有意义是不明智的)。
您至少应该在数据库中的两个字段上创建一个唯一键,并在保存更改时专门检查是否存在违反唯一键的异常。
此外,您可以(应该)在保存更改之前检查惟一值。最好的方法是使用Any()查询,因为它可以最小化传输的数据量:
if (context.Entities.Any(e => e.FirstColumn == value1
&& e.SecondColumn == value2))
{
// deal with duplicate values here.
}
请注意,单凭这张支票是远远不够的。在检查和实际提交之间总是有一些延迟,所以你总是需要唯一的约束+异常处理。
我想补充我的答案,因为提供的解决方案对我没有帮助。在我的例子中,其中一列是外键引用。
旧的模型:
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);
哪一种方法得到了想要的解决方案