質問
Fluent 構文または属性のいずれかを使用して、プロパティに一意の制約を定義することは可能ですか? 不可能な場合、回避策は何ですか?
主キーを持つユーザー クラスがありますが、電子メール アドレスも一意であることを確認したいと思います。データベースを直接編集せずにこれが可能ですか?
解決策(Mattの回答に基づく)
public class MyContext : DbContext {
public DbSet<User> Users { get; set; }
public override int SaveChanges() {
foreach (var item in ChangeTracker.Entries<IModel>())
item.Entity.Modified = DateTime.Now;
return base.SaveChanges();
}
public class Initializer : IDatabaseInitializer<MyContext> {
public void InitializeDatabase(MyContext context) {
if (context.Database.Exists() && !context.Database.CompatibleWithModel(false))
context.Database.Delete();
if (!context.Database.Exists()) {
context.Database.Create();
context.Database.ExecuteSqlCommand("alter table Users add constraint UniqueUserEmail unique (Email)");
}
}
}
}
ベストアンサー1
私の知る限り、現時点では Entity Framework でこれを行う方法はありません。ただし、これは一意制約だけの問題ではありません... インデックス、チェック制約、場合によってはトリガーやその他の構成要素も作成する必要があるかもしれません。使える簡単なパターンはこちらコードファーストの設定では、データベースに依存しないわけではありません。
public class MyRepository : DbContext {
public DbSet<Whatever> Whatevers { get; set; }
public class Initializer : IDatabaseInitializer<MyRepository> {
public void InitializeDatabase(MyRepository context) {
if (!context.Database.Exists() || !context.Database.ModelMatchesDatabase()) {
context.Database.DeleteIfExists();
context.Database.Create();
context.ObjectContext.ExecuteStoreCommand("CREATE UNIQUE CONSTRAINT...");
context.ObjectContext.ExecuteStoreCommand("CREATE INDEX...");
context.ObjectContext.ExecuteStoreCommand("ETC...");
}
}
}
}
もう 1 つのオプションは、ドメイン モデルがデータベースにデータを挿入/更新する唯一の方法である場合、一意性の要件を自分で実装し、データベースを除外することです。これはより移植性の高いソリューションであり、コード内のビジネス ルールを明確にする必要がありますが、データベースが不正なデータにバックドアされる危険性があります。