私は、Code Firstを使ってEF Entityを、そして流暢なAPIを使ってEntityTypeConfiguration
を構築しようとしています。主キーの作成は簡単ですが、一意制約ではそうではありません。私はこのためにネイティブSQLコマンドを実行することを提案した古い投稿を見ていましたが、それは目的を打ち負かしているようです。これはEF6で可能ですか?
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/ja-jp/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"にnique indexを追加します。
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 }));
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/ja-jp/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; }
}
}
これは、ユニークなインデックスをより滑らかに設定するための拡張方法です。
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" });
}
}
@ 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; }
残念ながら、これはEntity Frameworkではサポートされていません。これはEF 6のロードマップ上にありましたが、プッシュバックされました。 Workitem 299:Unique Constraints(Unique Indexes)
その間にこれがあります:
データベース内の他の行に対して一意のフィールドを検証するUniqueAttributeは、DataAnnotations.ValidationAttributeを継承します 。
コードをコピーしないですみません、少し長いです。