我想用Code First構建一個EF實體,並且使用流利的API來構建一個EntityTypeConfiguration
。創建主鍵很容易,但使用唯一約束並非如此。我看到的舊帖子建議爲此執行原生SQL命令,但這似乎破壞了目的。 EF6有可能嗎?用流暢的API設置唯一約束?
回答
在EF6.2上,您可以使用HasIndex()
爲通過流暢API遷移添加索引。
https://github.com/aspnet/EntityFramework6/issues/274
例
modelBuilder
.Entity<User>()
.HasIndex(u => u.Email)
.IsUnique();
在EF6.1起,您可以使用IndexAnnotation()
您流暢API中添加索引進行遷移。
http://msdn.microsoft.com/en-us/data/jj591617.aspx#PropertyIndex
您必須添加引用:
using System.Data.Entity.Infrastructure.Annotations;
基本示例
下面是一個簡單的使用,對User.FirstName
財產
modelBuilder
.Entity<User>()
.Property(t => t.FirstName)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
添加索引實際例子:
這裏是一個更現實的例子。它增加了一個唯一索引對多個屬性:User.FirstName
和User.LastName
,與索引名「IX_FIrstNameLastName」
modelBuilder
.Entity<User>()
.Property(t => t.FirstName)
.IsRequired()
.HasMaxLength(60)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_FirstNameLastName", 1) { IsUnique = true }));
modelBuilder
.Entity<User>()
.Property(t => t.LastName)
.IsRequired()
.HasMaxLength(60)
.HasColumnAnnotation(
IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_FirstNameLastName", 2) { IsUnique = true }));
不幸的是,這在實體框架中不受支持。這是在路線圖EF 6,但它得到了推後:Workitem 299: Unique Constraints (Unique Indexes)
作爲除了Yorro的答案,也可以通過使用屬性來完成。
樣品爲int
類型唯一鍵組合:
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)]
public int UniqueKeyIntPart1 { get; set; }
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)]
public int UniqueKeyIntPart2 { get; set; }
如果數據類型是string
,然後MaxLength
屬性必須被添加:
[Index("IX_UniqueKeyString", IsUnique = true, Order = 1)]
[MaxLength(50)]
public string UniqueKeyStringPart1 { get; set; }
[Index("IX_UniqueKeyString", IsUnique = true, Order = 2)]
[MaxLength(50)]
public string UniqueKeyStringPart2 { get; set; }
如果有一個域/存儲模型分離關注,使用Metadatatype
屬性/類可以是一個選項:https://msdn.microsoft.com/en-us/library/ff664465%28v=pandp.50%29.aspx?f=255&MSPPError=-2147217396
一個快速的控制檯應用程序,例如:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
namespace EFIndexTest
{
class Program
{
static void Main(string[] args)
{
using (var context = new AppDbContext())
{
var newUser = new User { UniqueKeyIntPart1 = 1, UniqueKeyIntPart2 = 1, UniqueKeyStringPart1 = "A", UniqueKeyStringPart2 = "A" };
context.UserSet.Add(newUser);
context.SaveChanges();
}
}
}
[MetadataType(typeof(UserMetadata))]
public class User
{
public int Id { get; set; }
public int UniqueKeyIntPart1 { get; set; }
public int UniqueKeyIntPart2 { get; set; }
public string UniqueKeyStringPart1 { get; set; }
public string UniqueKeyStringPart2 { get; set; }
}
public class UserMetadata
{
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 1)]
public int UniqueKeyIntPart1 { get; set; }
[Index("IX_UniqueKeyInt", IsUnique = true, Order = 2)]
public int UniqueKeyIntPart2 { get; set; }
[Index("IX_UniqueKeyString", IsUnique = true, Order = 1)]
[MaxLength(50)]
public string UniqueKeyStringPart1 { get; set; }
[Index("IX_UniqueKeyString", IsUnique = true, Order = 2)]
[MaxLength(50)]
public string UniqueKeyStringPart2 { get; set; }
}
public class AppDbContext : DbContext
{
public virtual DbSet<User> UserSet { get; set; }
}
}
如果要使域模型完全分開從存儲問題。 –
您還需要確保您具有對EntityFramework的引用 –
如果Index屬性與Entity Framework分離,那麼可以將其包含在我的Models項目中,這樣會很好。我明白這是一個存儲問題,但我使用它的主要原因是對UserNames和Role Names等東西施加了獨特的限制。 – Sam
@ coni2k的答案是正確的,但是你必須添加[StringLength]
屬性爲它工作,否則你會得到一個無效的鍵異常(例波紋管)。
[StringLength(65)]
[Index("IX_FirstNameLastName", 1, IsUnique = true)]
public string FirstName { get; set; }
[StringLength(65)]
[Index("IX_FirstNameLastName", 2, IsUnique = true)]
public string LastName { get; set; }
以下是更流暢設置唯一索引擴展方法:
public static class MappingExtensions
{
public static PrimitivePropertyConfiguration IsUnique(this PrimitivePropertyConfiguration configuration)
{
return configuration.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute { IsUnique = true }));
}
}
用法:
modelBuilder
.Entity<Person>()
.Property(t => t.Name)
.IsUnique();
會產生遷移,例如:
public partial class Add_unique_index : DbMigration
{
public override void Up()
{
CreateIndex("dbo.Person", "Name", unique: true);
}
public override void Down()
{
DropIndex("dbo.Person", new[] { "Name" });
}
}
的Src: Creating Unique Index with Entity Framework 6.1 fluent API
- 1. EF代碼第一流暢的API定義了唯一的約束
- 2. SQLAlchemy:UNIQUE約束失敗錯誤,但沒有設置唯一約束
- 3. 流暢的NHibernate加入約束
- 4. 唯一約束
- 5. 唯一約束在NON-NULL列上的唯一約束
- 6. 唯一約束Nhibernate
- 7. OpenERP唯一約束
- 8. oracle唯一約束
- 9. 唯一約束JayData
- 10. 唯一約束(SchemaName.DATA1_PK)
- 11. 唯一約束值
- 12. PostgreSQL的唯一約束不夠唯一
- 13. 在oracle 10g中對引用列設置唯一約束xe
- 14. DataTable上的唯一約束
- 15. Grails的唯一約束
- 16. SQLite中的唯一約束
- 17. 爲Db4oEmbedded EmbeddedConfiguration設置唯一的密鑰約束
- 18. 我如何設置基於其他列值的唯一約束
- 19. PostgreSQL中兩個唯一字段的設置約束
- 20. 如何在多列上設置唯一的約束條件
- 21. Sequelize:無法設置新的唯一約束消息
- 22. 設置Neo4j的唯一性約束在py2neo V3
- 23. 設置對值組合的唯一約束
- 24. 唯一約束vs唯一索引
- 25. Oracle唯一約束和唯一索引
- 26. 唯一約束的命名約定
- 27. XML模式唯一約束
- 28. JPA唯一約束驗證
- 29. Neo4JClient創建唯一約束
- 30. 笨ORA-00001:唯一約束
這需要將列註釋命名爲「索引」!我寫了另一個名字,它不起作用!我花了幾個小時才嘗試將它重命名爲原來的「索引」,就像在你的文章中一樣,並且明白這一點很重要。 :( 在框架中必須有一個不固定的代碼字符串。 –
該問題的有用鏈接!http://stackoverflow.com/questions/18889218/unique-key-constraints-for-multiple-columns -in-entity-framework –
@AlexanderVasilyev常量被定義爲'IndexAnnotation.AnnotationName' – Nathan