数時間の試行錯誤の後、同じ 2 つのタイプで一対多の関係と一対一の関係を確立する方法を説明するこのスレッドにたどり着きました。
ただし、カスケード削除でこれを機能させることはできません:
スローされる: 「依存操作の有効な順序を決定できません。外部キー制約、モデル要件、またはストアで生成された値が原因で、依存関係が存在する可能性があります。」(System.Data.UpdateException) Exception Message = "依存する操作の有効な順序を特定できません。依存関係は、外部キーの制約、モデルの要件、またはストアで生成された値が原因で存在する可能性があります。"、Exception Type = "System.Data.UpdateException "
これは、1:1 の関係 (以下のコードを参照) を設定解除していない場合にのみ発生します。無効な参照が作成されることを考えると、これは理にかなっていると思います。これを表現するためのより良い方法があるかどうか疑問に思っています。
サンプルコード:
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
using (var ctx = new Context())
{
var user = new User();
ctx.Users.Add(user);
ctx.SaveChanges();
var source = new PaymentSource();
user.PaymentSources = new Collection<PaymentSource>();
user.PaymentSources.Add(source);
user.DefaultPaymentSource = source;
ctx.SaveChanges();
// if I don't do this, I get ordering exception
user.DefaultPaymentSource = null;
ctx.SaveChanges();
ctx.Users.Remove(user);
ctx.SaveChanges();
Assert.Equal(0, ctx.Users.Count());
Assert.Equal(0, ctx.PaymentSources.Count());
}
}
}
public class User
{
public int Id { get; set; }
public virtual ICollection<PaymentSource> PaymentSources { get; set; }
public virtual PaymentSource DefaultPaymentSource { get; set; }
public int? DefaultPaymentSourceId { get; set; }
}
public class PaymentSource
{
public int Id { get; set; }
public virtual User User { get; set; }
public int UserId { get; set; }
}
public class Context : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<PaymentSource> PaymentSources { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>()
.HasOptional(u => u.DefaultPaymentSource)
.WithMany()
.HasForeignKey(u => u.DefaultPaymentSourceId)
.WillCascadeOnDelete(false);
modelBuilder.Entity<PaymentSource>()
.HasRequired(p => p.User)
.WithMany(p => p.PaymentSources)
.HasForeignKey(p => p.UserId)
.WillCascadeOnDelete();
}
}