C# EntityFrameworkでIDENTITY属性を無効化する
概要
EntityFrameworkではCodeFirstでDBを操作する際、主キーに対して自動でインクリメントのINDEXが付与される(IDENTITY属性)
キーを任意の数字としたかったので無効化した。
環境
- Windows 10 Pro (バージョン:1709)
- Visual Studio Community 2015 Update3
- Microsoft SQL Server Express
- .NET Framework 4.6
- EntityFramework 6.2
Model(オブジェクト)
class SelfDefenseShip { //護衛艦 public virtual EscortDivision EscortDivision { get; set; } //所属 public virtual HullCode HullCode { get; set; } //艦種記号 [Key] [Required] public int ShipNumber { get; set; } //艦識別番号 public string ShipName { get; set; } //艦名 public virtual ShipClass ShipClass { get; set; } //艦種型 public int StandardDisplacement { get; set; } //基準排水量(トン) public int FullLoadDisplacement { get; set; } //満載排水量(トン) public double FullLength { get; set; } //全長(メートル) public double FullWidth { get; set; } //全幅(メートル) public DateTime CommissionYear { get; set; } //就役(年) }
他に参照しているモデルがありますが、今回は関係ないので無視します。
キーとして艦識別番号を指定しています。
※こちらの写真が格好よかったので掲載していたのですが著作権的にNGなのでURLのみ記載しておきます。
画像にあるような船首の番号です。
艦情報のインサート
public void InsertShipData() { using (var db = new ShipsDbContext()) { using (var sr = new StreamReader(@"..\..\Data\ShipData.txt")) { var tmp = sr.ReadToEnd().Split(new string[] { "\r\n" }, StringSplitOptions.None); for (int i = 0; i < tmp.Length; i++) { var sdstmp = tmp[i].Split(new string[] { "\t" }, StringSplitOptions.None); //...中略 var sds = new SelfDefenseShip { ShipNumber = Int32.Parse(sdstmp[2]), //艦番号 ShipName = sdstmp[3] //艦名 //...中略 }; db.SelfDefenseShips.Add(sds); //データをインサート } db.SaveChanges(); //DBコミット } } }
用意した艦船情報を読み込みデータを追加します。
var sds = new SelfDefenseShip { ShipNumber = Int32.Parse(sdstmp[2]), //艦番号 ShipName = sdstmp[3] //艦名 //...中略 };
ShipNumberを主キーとするため艦船識別番号を格納しています。
IDENTITY属性が付与されている場合
ShipNumberに対して[Key]のアノテーションのみ付けている場合です。
インサート時に艦船番号を格納していますが、艦船番号がインクリメントされています。
問題点は以下のSQLです。
[ShipNumber] INT IDENTITY (1, 1) NOT NULL
自動でIDENTITY属性が付与されておりカウントアップされているようです。
IDENTITY属性を無効化した場合
モデルに対してアノテーションを付与します。
class SelfDefenseShip { //護衛艦 //...省略 [Key] [Required] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int ShipNumber { get; set; } //艦識別番号 //...省略 }
DatabaseGenerated属性のDatabaseGeneratedOptionを指定することによって
IDENTITY属性の振る舞いを指定することが出来ます。
今回は任意の値を指定したいのでnone
を指定します。
SQLからIDENTITY属性が消されました。
[ShipNumber] INT NOT NULL
データにも任意の艦船番号が入っており
こちらの意図した通りの動きとなっています。
参考サイト様
雑感
正直艦船番号が飛んでたりするので主キーとして採用するのはいかがなものかって感じですね。
恐らく重複は無いはず。