简体   繁体   English

实体框架7:确定关系

[英]Entity Framework 7: Identifying relationships

In previous versions of EF I can use following code to implement an identifying relationship: 在早期版本的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; }
}

It's needed to easily remove a child from collection like this: 需要像这样从集合中轻松删除一个孩子:

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

parent.Children.Remove(child);

_context.SaveChanges();

This approach is described in http://www.kianryan.co.uk/2013/03/orphaned-child/ (the method #2). 此方法在http://www.kianryan.co.uk/2013/03/orphaned-child/中进行了介绍(方法2)。

But in EF7 this code throws exception when migration is creating: 但是在EF7中,此代码在创建迁移时会引发异常:

An exception was thrown while executing a resolve operation. 执行解析操作时引发了异常。 See the InnerException for details. 有关详细信息,请参见InnerException。 ---> Entity type 'Child' has composite primary key defined with data annotations. --->实体类型“ Child”具有使用数据注释定义的复合主键。 To set composite primary key, use fluent API. 要设置复合主键,请使用fluent API。

I also tried to use FluentAPI as described in How to define nested Identifying Relationships Entity Framework code first in following code: 我还尝试按照以下代码中首先如何定义嵌套的识别关系实体框架代码中所述使用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);
    }

This approach allow generate a migration successfully, but when I tried to remove a child from Children collection I got following exception: 这种方法可以成功生成迁移,但是当我尝试从Children集合中删除一个孩子时,出现以下异常:

System.InvalidOperationException: The association between entity types 'Parent' and 'Child' has been severed but the foreign key for this relationship cannot be set to null. System.InvalidOperationException:实体类型“ Parent”和“ Child”之间的关联已被切断,但是此关系的外键不能设置为null。 If the dependent entity should be deleted, then setup the relationship to use cascade deletes. 如果应删除从属实体,则将关系设置为使用级联删除。

But I wouldn't like to use cascade deletes, I would like to use identifying relationship! 但是我不想使用级联删除,我想使用标识关系!

Please, help me understand what I do incorrect. 请帮助我了解我做错了什么。 Thank you! 谢谢!

Use cascade on delete instead as this is what it's used for: 请在删除时使用级联,因为它用于:

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

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

Just in case someone sees this error, let me tell you how I resolved mine: 以防万一有人看到此错误,让我告诉您我如何解决我的问题:

When you do an update, on EF you need to first query the database and get the data model, then map the Domain layer model with your changes onto it (basically copying fields onto the data), and finally call the DBContext update method, then save changes. 执行更新时,在EF上,您首先需要查询数据库并获取数据模型,然后将包含更改的域层模型映射到它(基本上将字段复制到数据上),最后调用DBContext更新方法,然后保存更改。

My problem was that my model (not the data model, the domain model) also had the sub objects on it. 我的问题是我的模型(不是数据模型,域模型)上也有子对象。

So here's the data layer model (for example): 因此,这是数据层模型(例如):

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

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

And here's how the domain layer model should be: 这是域层模型应为的方式:

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.
    }

When I was seeing the error, I had been using Autofac's runtime mapper to map the domain layer model's properties onto the data layer model. 当我看到错误时,我一直在使用Autofac的运行时映射程序将域层模型的属性映射到数据层模型上。 However, the child in the domain layer model was null, so it would nullify the data layer, causing the error: 但是,域层模型中的子级为null,因此它将使数据层无效,从而导致错误:

"The association between entity types 'Parent' and 'Child' has been severed but the foreign key for this relationship cannot be set to null. If the dependent entity should be deleted, then setup the relationship to use cascade deletes." “实体类型'Parent'和'Child'之间的关联已被切断,但是该关系的外键不能设置为null。如果应该删除从属实体,则设置该关系以使用级联删除。”


By the way, in the db context class, I have the following relationship defined: 顺便说一下,在数据库上下文类中,我定义了以下关系:

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

It's working. 工作正常

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

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