Bas*_*ili 222 entity-framework constraints unique-key multiple-columns ef-code-first
我正在使用Entity Framework 5.0 Code First;
public class Entity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string EntityId { get; set;}
public int FirstColumn { get; set;}
public int SecondColumn { get; set;}
}
Run Code Online (Sandbox Code Playgroud)
我想在两者之间进行组合,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
Run Code Online (Sandbox Code Playgroud)
反正有吗?
chu*_*uck 347
使用Entity Framework 6.1,您现在可以执行以下操作:
[Index("IX_FirstAndSecond", 1, IsUnique = true)]
public int FirstColumn { get; set; }
[Index("IX_FirstAndSecond", 2, IsUnique = true)]
public int SecondColumn { get; set; }
Run Code Online (Sandbox Code Playgroud)
属性中的第二个参数是您可以在其中指定索引中列的顺序的位置.
更多信息:MSDN
Bas*_*ili 108
我找到了三种解决问题的方法.
EntityFramework核心中的唯一索引:
第一种方法:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity>()
.HasIndex(p => new {p.FirstColumn , p.SecondColumn}).IsUnique();
}
Run Code Online (Sandbox Code Playgroud)
第二种使用备用密钥使用EF Core创建唯一约束的方法.
例子
一栏:
modelBuilder.Entity<Blog>().HasAlternateKey(c => c.SecondColumn).HasName("IX_SingeColumn");
Run Code Online (Sandbox Code Playgroud)
多列:
modelBuilder.Entity<Entity>().HasAlternateKey(c => new [] {c.FirstColumn, c.SecondColumn}).HasName("IX_MultipleColumns");
Run Code Online (Sandbox Code Playgroud)
EF 6及以下:
第一种方法:
dbContext.Database.ExecuteSqlCommand(string.Format(
@"CREATE UNIQUE INDEX LX_{0} ON {0} ({1})",
"Entitys", "FirstColumn, SecondColumn"));
Run Code Online (Sandbox Code Playgroud)
这种方法非常快速且有用,但主要问题是实体框架对这些更改一无所知!
第二种方法:
我在这篇文章中找到了它,但我没有亲自尝试过.
CreateIndex("Entitys", new string[2] { "FirstColumn", "SecondColumn" },
true, "IX_Entitys");
Run Code Online (Sandbox Code Playgroud)
这种方法的问题如下:它需要DbMigration,所以如果你没有它,你会怎么做?
第三种方法:
我认为这是最好的方法,但需要一些时间来完成.我将向您展示它背后的想法:在此链接http://code.msdn.microsoft.com/CSASPNETUniqueConstraintInE-d357224a中,
您可以找到唯一键数据注释的代码:
[UniqueKey] // Unique Key
public int FirstColumn { get; set;}
[UniqueKey] // Unique Key
public int SecondColumn { get; set;}
// The problem hier
1, 1 = OK
1 ,2 = NO OK 1 IS UNIQUE
Run Code Online (Sandbox Code Playgroud)
这种方法的问题; 我该如何组合它们?我有一个想法扩展这个Microsoft实现,例如:
[UniqueKey, 1] // Unique Key
public int FirstColumn { get; set;}
[UniqueKey ,1] // Unique Key
public int SecondColumn { get; set;}
Run Code Online (Sandbox Code Playgroud)
稍后在Microsoft示例中描述的IDatabaseInitializer中,您可以根据给定的整数组合键.但有一点需要注意:如果unique属性是string类型,那么你必须设置MaxLength.
nia*_*her 73
如果您使用的是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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
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);
Run Code Online (Sandbox Code Playgroud)
这将导致此迁移:
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");
}
Run Code Online (Sandbox Code Playgroud)
并最终在数据库中结束:
CREATE UNIQUE NONCLUSTERED INDEX [UQ_User_EmailPerApplication] ON [dbo].[User]
(
[Email] ASC,
[ApplicationId] ASC
)
Run Code Online (Sandbox Code Playgroud)
Adm*_*vić 16
您需要定义组合键.
使用数据注释,它看起来像这样:
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;}
}
Run Code Online (Sandbox Code Playgroud)
当通过指定覆盖OnModelCreating时,您也可以使用modelBuilder执行此操作:
modelBuilder.Entity<Entity>().HasKey(x => new { x.FirstColumn, x.SecondColumn });
Run Code Online (Sandbox Code Playgroud)
完成使用带外键的复合索引的 @chuck答案.
您需要定义一个包含外键值的属性.然后,您可以在索引定义中使用此属性.
例如,我们公司有员工,只有我们对任何员工(名称,公司)有独特的约束:
class Company
{
public Guid Id { get; set; }
}
class Employee
{
public Guid Id { get; set; }
[Required]
public String Name { get; set; }
public Company Company { get; set; }
[Required]
public Guid CompanyId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在Employee类的映射:
class EmployeeMap : EntityTypeConfiguration<Employee>
{
public EmployeeMap ()
{
ToTable("Employee");
Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
Property(p => p.Name)
.HasUniqueIndexAnnotation("UK_Employee_Name_Company", 0);
Property(p => p.CompanyId )
.HasUniqueIndexAnnotation("UK_Employee_Name_Company", 1);
HasRequired(p => p.Company)
.WithMany()
.HasForeignKey(p => p.CompanyId)
.WillCascadeOnDelete(false);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我还使用@niaher扩展名进行唯一索引注释.
niaher的回答指出,要使用Fluent API,您需要自定义扩展名,在撰写本文时可能是正确的。您现在可以(EF core 2.1)如下使用fluent API:
modelBuilder.Entity<ClassName>()
.HasIndex(a => new { a.Column1, a.Column2}).IsUnique();
Run Code Online (Sandbox Code Playgroud)
对于那些寻找 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;}
}
Run Code Online (Sandbox Code Playgroud)
这样注释应该存在于模型而不是单个列上。还要注意nameof()语法。
这个答案来自官方文档:https : //docs.microsoft.com/en-us/ef/core/modeling/indexes?tabs=data-annotations
小智 5
在@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; }
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
150573 次 |
| 最近记录: |