繁体   English   中英

实体框架5.0b2代码优先:同一表的一对多和一对一,带有级联删除

[英]Entity Framework 5.0b2 Code First: One-To-Many and One-To-One for the same table, WITH Cascade Delete

经过数小时的反复试验,我到达了该线程 ,该线程说明了如何使用相同的两种类型建立一对多关系和一对一关系。

但是,我无法将其与Cascade Delete一起使用:

抛出:“无法确定相关操作的有效顺序。由于外键约束,模型要求或存储生成的值,可能存在相关性。” (System.Data.UpdateException)异常消息=“无法确定相关操作的有效顺序。由于外键约束,模型要求或存储生成的值,可能存在依赖性。”,异常类型=“ 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();
    }
}

我列出了其他选项来描述您的抽象:

一种。

如何使用3个这样的表:

user 1-* paymentSource
user 1-0..1 DefaultPaymentSource
DefaultPaymentSource 0..1-1 PaymentSource

或这个:

B.

user 1-* paymentSource
user 1-0..1 DefaultPaymentSource
DefaultPaymentSource --derive from--> PaymentSource

或这个:

C。

user 1-* paymentSource
PaymentSource has addtional boolean field for "IsDefault"

我投票选择B为最佳选择。

我确信从同一个源表到同一个目标表有两个关系并不是一个好主意。这可能会破坏有关数据库最佳实践的某些规则或模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM