私は次のクラス構造を持っています:
カードテーブルに識別関係を入れるようにFluent APIを設定する方法は?
つまり
- カード テーブル PK: Id、CustomerId
- カード テーブル FK: CustomerId
Customer.Card プロパティに新しいカードを割り当てるときに、以前のカードを削除したいと思います。
したがって、クラスを次のように定義しました。
public class Customer
{
public int Id { get; private set; }
public virtual Card Card { get; set; }
}
public abstract class Card
{
public int Id { get; private set; }
}
public class Visa : Card
{
}
public class Amex : Card
{
}
DbContext は次のようになります。
public class Context : DbContext
{
public DbSet<Customer> Customers { get; set; }
public DbSet<Card> Cards { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>()
.HasRequired(c => c.Card)
.WithRequiredPrincipal()
.Map(a => a.MapKey("CustomerId"))
.WillCascadeOnDelete();
modelBuilder.Entity<Card>();
}
}
テストは次のとおりです。
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var context = new Context();
var customer = new Customer();
context.Customers.Add(customer);
customer.Card = new Visa();
context.SaveChanges();
customer.Card = new Amex();
context.SaveChanges();
Assert.AreEqual(1, context.Customers.Count());
Assert.AreEqual(1, context.Cards.Count());
}
}
まったく機能しません。私はこれを2回目の保存で持っていますが、ここで識別関係を指定する方法がわかりません:
未処理の例外: System.Data.Entity.Infrastructure.DbUpdateException: リレーションシップの外部キー プロパティを公開しないエンティティの保存中にエラーまたは発生しました。単一のエンティティを例外のソースとして識別できないため、EntityEntries プロパティは null を返します。保存中の例外イオンの処理は、エンティティ タイプで外部キー プロパティを公開することで簡単に行うことができます。詳細については、InnerException を参照してください。---> System.Data.Entity.Core.U pdateException: 「Customer_Card」AssociationSet からの関係が「削除済み」状態です。多重度の制約がある場合、対応する「Customer_Card _Target」も「削除済み」状態でなければなりません。
更新1 対多の関係で機能させるのは簡単です。以下に完全な例を示します。
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var context = new Context();
var customer = new Customer();
context.Customers.Add(customer);
customer.Cards.Add(new Visa());
context.SaveChanges();
customer.Cards[0] = new Amex();
context.SaveChanges();
Assert.AreEqual(1, context.Cards.Count());
}
}
public class Customer
{
public Customer()
{
Cards = new List<Card>();
}
public int Id { get; private set; }
public virtual List<Card> Cards { get; set; }
}
public abstract class Card
{
public int Id { get; private set; }
public int CustomerId { get; private set; }
}
public class Visa : Card
{
}
public class Amex : Card
{
}
public class Context : DbContext
{
static Context()
{
Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
}
public DbSet<Customer> Customers { get; set; }
public DbSet<Card> Cards { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Customer>()
.HasMany(c => c.Cards)
.WithRequired()
.HasForeignKey(c => c.CustomerId)
.WillCascadeOnDelete();
modelBuilder.Entity<Card>()
.HasKey(c => new { c.Id, c.CustomerId });
}
}