2012-05-16 9 views
80

私はEntity Framework 4.3を使用しており、Code Fistを使用しています。Entity Frameworkコードの最初の一意の列

私はどうやってユーザ名がデータベーステーブルを作成するときに一意である必要があることをEntity Frameworkのクラスを

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

を言うのですか? 可能であれば、構成ファイルの代わりにデータアノテーションを使用することをお勧めします。

答えて

-13

EF4.3

ユニークユーザー名

としてカラムにデータアノテーションを追加のためのソリューション:私は上飾り[キー]を追加した 、

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

一意のID私の列と完了。ここで説明するように 同じ溶液:https://msdn.microsoft.com/en-gb/data/jj591583.aspx

IE:

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

代替マッピング

を使用して、データ注釈

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

に使用して

答えます

+24

この解決策には注意してください。 'UserName'プロパティに' Key'属性を追加すると 'UserName'プロパティがデータベースの主キーになります。 'UserId'プロパティだけが' Key'属性でマークされるべきです。このソリューションは、誤ったデータベース設計をしながらプログラミング側で「正しい」動作を提供します。 –

+4

funny -10 accepted answer :) –

20

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

+1

これはまさに私が探していたものです!私は移行を使ってそのような制約を加えることが可能かどうか疑問に思っていました。 –

+0

@Ladislav Mrnka:これはSeedメソッドでも可能ですか? –

+1

例を提供するのに気をつけますか?ありがとう! – Zero3

5

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

170

6.1以降、あなたのモデルにこの属性を使用することができます。

[Index(IsUnique=true)] 

あなたがこの名前空間にそれを見つけることができます。

using System.ComponentModel.DataAnnotations.Schema; 

モデルフィールドが文字列である場合は、確認してくださいSQL Serverでnvarchar(MAX)に設定されていないか、Entity Frameworkコードファーストでこのエラーが表示されます。

テーブル 'dbo.y' iの列 'x'索引のキー列として使用するには無効な型のキーです。

理由は、このためです:

SQL Serverは、すべてのインデックスキー列の最大合計サイズ900バイトの制限を保持します。「(から: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;} 
} 

更新:

あなたが流暢使用する場合:

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

+14

この男の古いポストに返信してくれてありがとう! –

+2

StringLengthの設定が機能しました。素晴らしい答え。 – vidriduch

+1

なぜインデックスではなく、単に制約ですか? –

8

コードから、POCOを使用することが明らかになります。別のキーを使用する必要はありません。juFoのようにインデックスを追加できます。

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

これは、次のSQLスクリプトを作成します:あなたは次のようになります。代わりに、UserNameプロパティをあなたの列の注釈を帰するの流暢APIを使用している場合
あなたが持つ複数のユーザーを挿入しようとすると

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では使用できません。

関連する問題