实体框架7:识别关系

时间:2016-03-15 14:49:28

标签: c# entity-framework entity-framework-core ef-fluent-api

在以前版本的EF中,我可以使用以下代码来实现识别关系:

public class Child
{
    [Key, Column(Order = 1)]
    public virtual int Id { get; set; }

    [Key, Column(Order = 2)]
    public virtual int ParentId { get; set; }
    public virtual Parent Parent { get; set; }
}

需要从这样的集合中轻松删除一个孩子:

var parent = _context.Parents.First();
var child = parent.Children.First();

parent.Children.Remove(child);

_context.SaveChanges();

http://www.kianryan.co.uk/2013/03/orphaned-child/(方法#2)中描述了这种方法。

但在EF7中,此代码在创建迁移时抛出异常:

  

执行解析操作时抛出异常。见   InnerException以获取详细信息。 --->实体类型'Child'具有复合   使用数据注释定义的主键。设置复合主要   密钥,使用流畅的API。

我还尝试按照How to define nested Identifying Relationships Entity Framework code first中的说明在以下代码中使用FluentAPI:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Parent>()
            .HasMany(p => p.Children)
            .WithOne(c => c.Parent);

        modelBuilder.Entity<Child>()
            .HasKey(c => new {c.Id, c.ParentId});

        base.OnModelCreating(modelBuilder);
    }

此方法允许成功生成迁移,但是当我尝试从Children集合中删除子项时,我遇到以下异常:

  

System.InvalidOperationException:实体类型之间的关联   '父母'和'孩子'已被切断,但外键是这个   关系不能设置为null。如果依赖实体应该是   删除,然后设置关系以使用级联删除。

但我不想使用级联删除,我想使用识别关系!

请帮助我理解我做错了什么。谢谢!

2 个答案:

答案 0 :(得分:2)

在删除时使用级联,因为这是它用于:

modelBuilder.Entity<Parent>()
    .HasMany(p => p.Children)
    .WithOne(c => c.Parent);
    .WillCascadeOnDelete(true);

https://msdn.microsoft.com/en-gb/data/jj591620.aspx

答案 1 :(得分:0)

以防万一有人看到此错误,让我告诉您我如何解决我的问题:

进行更新时,在EF上,您首先需要查询数据库并获取数据模型,然后将更改后的域层模型映射到数据库上(基本上将字段复制到数据上),最后调用DBContext更新方法,然后保存更改。

我的问题是我的模型(不是数据模型,域模型)上也有子对象。

这是数据层模型(例如):

public class Parent
{
   public int ChildId {get; set; }

   [ForeignKey("ChildId")]
   public virtual Child Child { get; set; }
}

这是域层模型应为的方式:

public class Parent
    {
        public int ChildId { get; set; }
        //public Child Child { get; set; }  // this caused the error, keep reading if you want to know more.
    }

当我看到错误时,我一直在使用Autofac的运行时映射器将域层模型的属性映射到数据层模型上。但是,域层模型中的子级为null,因此它将使数据层无效,从而导致错误:

“实体类型'Parent'和'Child'之间的关联已被切断,但是该关系的外键不能设置为null。如果应该删除从属实体,则设置该关系以使用级联删除。”


在数据库上下文类中,我定义了以下关系:

modelBuilder.Entity<Parent>()
   .HasOne(a => a.Child)
   .WithMany()
   .HasForeignKey(p => p.ChildId)
   .OnDelete(DeleteBehavior.Restrict);

正在工作。