EF Core中是否有唯一约束的数据注释(代码优先)?

我想知道在Entity Framework Core 2代码第一种方法中是否存在唯一约束的数据注释?

在EF Core中您只能在流畅的API中使用扩展方法HasAlternateKey没有数据注释来实现唯一约束

这篇MS doc文章 – 备用键(唯一约束) – 将解释如何使用以及存在哪些其他可能性。

以上链接的简短示例:

 class MyContext : DbContext { public DbSet Cars { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .HasAlternateKey(c => c.LicensePlate) .HasName("AlternateKey_LicensePlate"); } } class Car { public int CarId { get; set; } public string LicensePlate { get; set; } public string Make { get; set; } public string Model { get; set; } } 

此外,还可以定义唯一索引 。 因此,在EF Core中,您必须在Fluent API中使用扩展方法HasIndex无数据注释 )。 在这篇MS doc文章 – 索引中 – 您将找到更多信息。

这里是一个唯一索引的示例:

 class MyContext : DbContext { public DbSet Blogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .HasIndex(b => b.Url) .IsUnique(); } } public class Blog { public int BlogId { get; set; } public string Url { get; set; } } 

我编写了一个Attribute类,它允许您装饰EF Core Entity类属性以生成Unique Key(不使用Fluent API)。

 using System; using System.ComponentModel.DataAnnotations; ///  /// Used on an EntityFramework Entity class to mark a property to be used as a Unique Key ///  [AttributeUsageAttribute(AttributeTargets.Property, AllowMultiple = true, Inherited = true)] public class UniqueKeyAttribute : ValidationAttribute { ///  /// Marker attribute for unique key ///  /// Optional, used to group multiple entity properties together into a combined Unique Key /// Optional, used to order the entity properties that are part of a combined Unique Key public UniqueKeyAttribute(string groupId = null, int order = 0) { GroupId = groupId; Order = order; } public string GroupId { get; set; } public int Order { get; set; } } 

在您的DbContext.cs文件中,在OnModelGenerating(modelBuilder)方法中,添加以下内容:

 // Iterate through all EF Entity types foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { #region Convert UniqueKeyAttribute on Entities to UniqueKey in DB var properties = entityType.GetProperties(); if ((properties != null) && (properties.Any())) { foreach (var property in properties) { var uniqueKeys = GetUniqueKeyAttributes(entityType, property); if (uniqueKeys != null) { foreach (var uniqueKey in uniqueKeys.Where(x => x.Order == 0)) { // Single column Unique Key if (String.IsNullOrWhiteSpace(uniqueKey.GroupId)) { entityType.AddIndex(property).IsUnique = true; } // Multiple column Unique Key else { var mutableProperties = new List(); properties.ToList().ForEach(x => { var uks = GetUniqueKeyAttributes(entityType, x); if (uks != null) { foreach (var uk in uks) { if ((uk != null) && (uk.GroupId == uniqueKey.GroupId)) { mutableProperties.Add(x); } } } }); entityType.AddIndex(mutableProperties).IsUnique = true; } } } } } #endregion Convert UniqueKeyAttribute on Entities to UniqueKey in DB } 

同样在您的DbContext.cs类中,添加以下私有方法:

 private static IEnumerable GetUniqueKeyAttributes(IMutableEntityType entityType, IMutableProperty property) { if (entityType == null) { throw new ArgumentNullException(nameof(entityType)); } else if (entityType.ClrType == null) { throw new ArgumentNullException(nameof(entityType.ClrType)); } else if (property == null) { throw new ArgumentNullException(nameof(property)); } else if (property.Name == null) { throw new ArgumentNullException(nameof(property.Name)); } var propInfo = entityType.ClrType.GetProperty( property.Name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); if (propInfo == null) { return null; } return propInfo.GetCustomAttributes(); } 

在Entity.cs类中的用法:

 public class Company { [Required] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid CompanyId { get; set; } [Required] [UniqueKey(groupId: "1", order: 0)] [StringLength(100, MinimumLength = 1)] public string CompanyName { get; set; } } 

您甚至可以在多个属性中使用它来在表格的多个列中形成唯一键。 (注意使用“groupId”然后“订单”)

 public class Company { [Required] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid CompanyId { get; set; } [Required] [UniqueKey(groupId: "1", order: 0)] [StringLength(100, MinimumLength = 1)] public string CompanyName { get; set; } [Required] [UniqueKey(groupId: "1", order: 1)] [StringLength(100, MinimumLength = 1)] public string CompanyLocation { get; set; } }