添加相关实体而不使用导航属性 [英] Adding Related Entities without using navigation properties

查看:109
本文介绍了添加相关实体而不使用导航属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程,设置为测试:

I have the following classes, set for testing:

public class Company
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Employee
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string Name { get; set; }

    public int CompanyId { get; set; }
    public virtual Company Company { get; set; }
}

public class EFTestDbContext : DbContext
{
    public DbSet<Employee> Employees { get; set; }
    public DbSet<Company> Companies { get; set; }
}

为了测试,我想插入一个公司和一个员工对于该公司,使用单个SaveChanges调用,如下所示:

For the sake of testing, I wanted to insert one company and one employee for that company with single SaveChanges call, like this:

Company company = new Company
{
    Name = "Sample company"
};

context.Companies.Add(company);

// ** UNCOMMENTED FOR TEST 2
//Company company2 = new Company
//{
//    Name = "Some other company"
//};
//context.Companies.Add(company2);

Employee employee = new Employee
{
    Name = "Hans",
    CompanyId = company.Id
};
context.Employees.Add(employee);

context.SaveChanges();

即使我没有使用导航属性,而是与Id建立关系,神秘的工作 - 员工被保存了适当的外键,公司从0更新到真正的价值,这让我走了!一些隐藏的C#功能?

Even though I am not using navigational properties, but instead I've made relation over Id, this somehow mysteriously worked - employee was saved with proper foreign key to company which got updated from 0 to real value, which made me go ?!?! Some hidden C# feature?

然后,我决定添加更多的代码,这在上面的代码片段中被注释,使其成为2 x公司实体和1 x员工实体,然后我有异常:

Then I've decided to add more code, which is commented in the snippet above, making it to be inserting of 2 x Company entity and 1 x Employee entity, and then I got exception:


无法确定CodeLab.EFTest.Employee_Company关系的主体结束。多个添加的实体可能具有相同的主键。

Unable to determine the principal end of the 'CodeLab.EFTest.Employee_Company' relationship. Multiple added entities may have the same primary key.

这是否意味着在外键为0的情况下,匹配实体插入到相同的SaveChanges事务中,Entity Framework会假定外键应该是匹配的实体?

Does this mean that in cases where foreign key is 0, and there is a single matching entity being inserted in same SaveChanges transaction, Entity Framework will assume that foreign key should be for that matching entity?

在第二个测试中,当有两个实体匹配关系类型,实体框架抛出异常,因为它不能弄清哪些员工应该与哪个员工相关。

In second test, when there are two entities matching the relation type, Entity Framework throws an exception as it is not able to figure out to which of the Companies Employee should be related to.

编辑:

我已经做了一个测试,并评论了一行。第一个测试仍然正常运行(因为int的默认值为0):

I've done one more test, and commented out one line. First test still runs properly (since default value for int is 0):

Employee employee = new Employee
{
    Name = "Hans",
    //CompanyId = company.Id // * no need for this at all
};


推荐答案

您没有真正碰到隐藏的C#功能,可能是一个晦涩的实体框架功能。

You're not really hitting a hidden C# feature, maybe an obscure Entity Framework feature.

当您分配 CompanyId 时,EF知道该公司拥有 Id = 0 (此时)是员工的父母。在许多情况下, EF执行 DetectChanges ,它也执行 relationship fixup :匹配外键值和引用。当您执行

When you assign the CompanyId, EF knows that the the company having Id = 0 (at that moment) is the employee's parent. On numerous occasions, EF executes DetectChanges, which also executes relationship fixup: matching foreign key values and references. This happens when you execute

context.Employees.Add(employee);

现在,EF将使用引用而不是外键值,因此它知道哪个FK值存储在数据库中。

Now EF will use the reference, rather than the foreign key value, so it knows which FK value to store in the database.

创建两个公司时,有两个实例具有相同的临时密钥值,所以EF不能再选择。

When you create two companies, there are two instances having the same transient key value, so EF can't choose anymore.

所以当你想存储新的连接对象时,总是建议设置引用而不是FK值。

So when you want to store new connected objects it's always recommended to set references in stead of FK values.

这篇关于添加相关实体而不使用导航属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆