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


114

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

クラスがあります

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

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

回答:


257

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

アップデート3

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

アップデート4

ASP.NET Core Mvc 2.2とEF Core:

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

23
この人の古い投稿に関連する最新情報を返信していただきありがとうございます。
— ジムヤーブロ2014

3
なぜインデックスなのか、なぜ制約だけなのか?
— John Henckel、2015年

2
インデックスと"There are no significant differences between creating a UNIQUE constraint and creating a unique index that is independent of a constraint. Data validation occurs in the same manner, and the query optimizer does not differentiate between a unique index created by a constraint or manually created. However, creating a UNIQUE constraint on the column makes the objective of the index clear."
— 制約の

3
注意; でEntity Frameworkのコア1.0.0-preview2決勝Aデータアノテーション方法が利用可能でない- docs.efproject.net/en/latest/modeling/...
— エドワードコモー

26

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


1
それがまさに私が探していたものです!移行を使用してそのような制約を追加することが可能かどうか疑問に思っていました。
— Alex Jorgenson、2012年

@Ladislav Mrnka:これはシードメソッドでも可能ですか?
— Raheel Khan

2
例を提供しますか?ありがとう!
— Zero3、2016年

10

コードから、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では使用できません。


構成を使用して複数の列を持つインデックスを作成するのはどうですか?
— FindOutIslamNow 2018年

1つはUserNameにあり、もう1つは何ですか?
— Alexander Christov 2018年

5

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



-13

EF4.3のソリューション

一意のユーザー名

次のように列にデータ注釈を追加します:

 [Index(IsUnique = true)]
 [MaxLength(255)] // for code-first implementations
 public string UserName{get;set;}

一意のID 、列に装飾[Key]を追加して完了しました。ここで説明されているのと同じソリューション:https : //msdn.microsoft.com/en-gb/data/jj591583.aspx

IE:

[Key]
public int UserId{get;set;}

別の答え

データ注釈の使用

[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("UserId")]

マッピングの使用

  mb.Entity<User>()
            .HasKey(i => i.UserId);
        mb.User<User>()
          .Property(i => i.UserId)
          .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
          .HasColumnName("UserId");

25
このソリューションには注意してください。プロパティにKey属性を追加すると、UserNameプロパティがUserNameデータベースの主キーになります。UserIdプロパティのみをKey属性でマークする必要があります。このソリューションは、プログラミング側で「正しい」動作を提供すると同時に、不適切なデータベース設計を提供します。
— Alex Jorgenson、2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.