ポイント
[Index(IsUnique=true)]
という Annotation 属性をプロパティに付けることでそのカラムは一意となる。- プロパティの型が String の場合、MaxLength も付ける必要がある。一意性をチェックするためには、カラムへの格納サイズが無限とも思われる String だとパフォーマンスが大きく低下するためと思われる。
モデルのコード
public class Sex { public int Id { get; set; } [Required] [Index(IsUnique=true)] [MaxLength(10)] public string Name { get; set; } }
もし MaxLength 属性を付けなかった場合は、どうなったか?
Add-Migration
コマンドは、正常に実行できました。
ところが、Update-Database
コマンドで例外となりました。
Name カラムが NVARCHAR (MAX) のまま、ユニークインデックスを付けることはできないのですね><。
PM> Update-Database -Verbose
Using StartUp project ‘Sample1’.
Using NuGet project ‘Sample1’.
Specify the ‘-Verbose’ flag to view the SQL statements being applied to the target database.
Target database is: ‘Sample1Context-20151016212614’ (DataSource: (localdb)\MSSQLLocalDB, Provider: System.Data.SqlClient, Origin: Configuration).
Applying explicit migrations: [201511121308078_AddUniqueToSexName].
Applying explicit migration: 201511121308078_AddUniqueToSexName.
CREATE UNIQUE INDEX [IX_Name] ON [dbo].Sexes
System.Data.SqlClient.SqlException (0x80131904): Column ‘Name’ in table ‘dbo.Sexes’ is of a type that is invalid for use as a key column in an index.
場所 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
… 略 …
場所 System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
ClientConnectionId:b86455ca-327e-4622-9c29-53bf8922f2df
Error Number: 1919、State: 1、Class: 16
Column ‘Name’ in table ‘dbo.Sexes’ is of a type that is invalid for use as a key column in an index.
PM>
ユニークインデックスをつけたところ、アプリの画面から既存の値を追加しようとするとどうなったか?
性別マスタに「男」「女」とすでに登録済みの状態から、さらに「女」を追加しようとしたところ、次の例外が発生して追加はできませんでした。
予定通りとなりました♪
[SqlException (0x80131904): Cannot insert duplicate key row in object ‘dbo.Sexes’ with unique index ‘IX_Name’. The duplicate key value is (女).
The statement has been terminated.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +2418102
… 略 …
回避するにはどうしたらよいかしら?次の2案が思い浮かびますの。
- 事前にチェックをする。
- 例外をキャッチする。
例外の実行コストは高い(と目にしたことがあります)ことや、例外の用途を考えますと、事前にチェックをするのがよさそうですわね♪
チェックとして、独自の検証属性を作るとよいかしら?一度データベースへの問い合わせが発生しますから、少し難易度が高いかしら?
なお、自作の検証属性クラスは、以前の投稿で少し取り組んでおります。
おわりに
次のページが参考になりました!ありがとう存じます♪
- Entity Framework 6.1のコードファーストでのインデックス作成 – 10パーの日記
カラムをユニークにするために、SQL Server にはユニークインデックスというものがあることを知ることができました♪ - sql – is of a type that is invalid for use as a key column in an index – Stack Overflow
ユニークインデックスをテーブルに作成できない原因と、解決策を知ることができました♪
以上です。