web-dev-qa-db-ja.com

Entity Frameworkコードの最初の一意の列

Entity Framework 4.3とCode Fistを使用しています。

クラスがあります

public class User
{
   public int UserId{get;set;}
   public string UserName{get;set;}
}

データベーステーブルを作成するときにUserNameが一意でなければならないことをEntity Frameworkに伝えるにはどうすればよいですか?可能であれば、構成ファイルの代わりにデータ注釈を使用したいと思います。

102
cpoDesign

Entity Framework 6.1以降では、モデルで次の属性を使用できます。

[Index(IsUnique=true)]

この名前空間で見つけることができます:

using System.ComponentModel.DataAnnotations.Schema;

モデルフィールドが文字列の場合、SQL Serverでnvarchar(MAX)に設定されていないことを確認してください。設定されていない場合、Entity Framework Code Firstでこのエラーが表示されます。

テーブル 'dbo.y'の列 'x'は、インデックスのキー列として使用するには無効なタイプです。

その理由は次のとおりです。

SQL Serverは、すべてのインデックスキー列の最大合計サイズについて900バイトの制限を保持しています。」

(from: http://msdn.Microsoft.com/en-us/library/ms191241.aspx

これを解決するには、モデルに最大文字列長を設定します。

[StringLength(450)]

EF CF 6.1+では、モデルは次のようになります。

public class User
{
   public int UserId{get;set;}
   [StringLength(450)]
   [Index(IsUnique=true)]
   public string UserName{get;set;}
}

更新:

fluentを使用する場合:

  public class UserMap : EntityTypeConfiguration<User>
  {
    public UserMap()
    {
      // ....
      Property(x => x.Name).IsRequired().HasMaxLength(450).HasColumnAnnotation("Index", new IndexAnnotation(new[] { new IndexAttribute("Index") { IsUnique = true } }));
    }
  }

modelBuilderで使用します。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  // ...
  modelBuilder.Configurations.Add(new UserMap());
  // ...
}

更新2

entityFrameworkCoreについては、このトピックも参照してください。 https://github.com/aspnet/EntityFrameworkCore/issues/1698

Update 3

eF6.2の場合: https://github.com/aspnet/EntityFramework6/issues/274

4を更新

ASP.NET Core Mvc 2.2 with EF Core:

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Unique { get; set; }
223
juFo

EFは、キー以外の一意の列をサポートしていません。 EF Migrationsを使用している場合は、EFにUserName列に一意のインデックスを(注釈ではなく移行コードで)作成させることができますが、一意性はデータベースでのみ強制されます。重複する値を保存しようとすると、データベースによって起動された例外(制約違反)をキャッチする必要があります。

25
Ladislav Mrnka

コードから、POCOを使用していることが明らかになります。別のキーを持つ必要はありません: juFo で示唆されているようにインデックスを追加できます。
UserNameプロパティを指定する代わりにFluent APIを使用する場合、列の注釈は次のようになります。

this.Property(p => p.UserName)
    .HasColumnAnnotation("Index", new IndexAnnotation(new[] { 
        new IndexAttribute("Index") { IsUnique = true } 
    }
));

これにより、次のSQLスクリプトが作成されます。

CREATE UNIQUE NONCLUSTERED INDEX [Index] ON [dbo].[Users]
(
    [UserName] ASC
)
WITH (
    PAD_INDEX = OFF, 
    STATISTICS_NORECOMPUTE = OFF, 
    SORT_IN_TEMPDB = OFF, 
    IGNORE_DUP_KEY = OFF, 
    DROP_EXISTING = OFF, 
    ONLINE = OFF, 
    ALLOW_ROW_LOCKS = ON, 
    ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]

同じUserNameを持つ複数のユーザーを挿入しようとすると、次のメッセージを含むDbUpdateExceptionが発生します。

Cannot insert duplicate key row in object 'dbo.Users' with unique index 'Index'. 
The duplicate key value is (...).
The statement has been terminated.

この場合も、バージョン6.1より前のEntity Frameworkでは列注釈を使用できません。

9

Entity Framework 6.1(現在ベータ版)では、IndexAttributeをサポートして、Code First Migrationsで(一意の)インデックスを自動的に作成するインデックスプロパティに注釈を付けることに注意してください。

5
Robba