当前位置: 首页 > 面试题库 >

在不使用导航属性的情况下添加相关实体

魏浩广
2023-03-14
问题内容

我有以下用于测试的类:

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调用插入一家公司和该公司的一名员工,如下所示:

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#功能?

然后,我决定添加更多代码,上面的代码段中对此进行了注释,使其插入了2个Company实体和1个Employee实体,然后出现异常:

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

这是否意味着在外键为0且在同一SaveChanges事务中插入单个匹配实体的情况下,实体框架将假定外键应用于该匹配实体?

在第二项测试中,当有两个匹配关系类型的实体时,实体框架将引发异常,因为它无法确定应与哪个公司雇员相关。

编辑:

我又做了一个测试,并注释了一行。第一个测试仍然可以正常运行(因为int的默认值为0):

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

问题答案:

您并没有真正找到隐藏的C#功能,也许是不起眼的Entity Framework功能。

当您分配时CompanyId,EF知道Id = 0(当时)拥有的公司是员工的母公司。在很多情况下,EF执行DetectChanges,它还会执行
关系修正 :匹配外键值和引用。执行时会发生这种情况

context.Employees.Add(employee);

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

当您创建两家公司时,有两个实例具有相同的临时键值,因此EF无法再选择了。

因此,当您要存储新的连接html" target="_blank">对象时,始终建议您设置引用而不是FK值。



 类似资料:
  • 我使用Spring Data Neo4J 5.0.10与Spring Boot 2.0.5。节点I具有以下2个实体,用户兴趣实体和用户兴趣实体的关系。 这很有效。我可以创建一个新用户并将该用户与userInterest关联。当我再次发送相同的详细信息时,节点和边不会重复。 当我在关系实体中启用权重属性时,即使权重属性值相同,关系似乎也是重复的。 我记得我读到过,只要属性相同,就不应该创建另一种关系

  • 问题内容: 当前,当浏览器宽度降至768px以下时,导航栏将变为折叠模式。我想将此宽度更改为1000px,所以当浏览器低于1000px时,导航栏将变为折叠模式。我想在不使用LESS的情况下执行此操作,而是在使用手写笔而不是LESS。 我的问题与此问题相同:Bootstrap 3Navbar折叠 但是,这些问题中的所有答案都说明了如何通过更改LESS变量来做到这一点。我没有接触过LESS,我正在使用

  • 我想使用android jetpack的新导航库。当我想将导航XML添加到我的项目中时,我遇到了一个错误,错误是: 此操作需要android库。拱导航:导航片段:,android。拱导航:导航用户界面:。 问题:发现现有项目依赖项中存在不一致。之间的版本不兼容:-android。拱坚持不懈房间:运行时:1.1.1和:-com。Android支持:appcompat-v7:27.1.1 使用依赖项:

  • 问题内容: 我有两个实体: 保存首选项时,我具有accountId,但没有Account实体。在这种情况下,如何保存首选项? 加载帐户实体并在首选项上进行设置?对我来说,这似乎是对数据库的错误旅行。 是否具有一个可持久保存的accountId字段并使Account字段为只读?同时拥有一个accountId字段和一个Account字段似乎多余吗? 使用NamedQuery保留首选项?我希望只是通用地

  • 我试图验光一些报告,并试图删除需要加载一些昂贵的相关记录(多个级联加载,每个约500条记录)。 我的实体是这样的: 以及: 我的问题是,当我做这个调用:Hibernate去实例化Foo实体,并加载所有相关的记录,即使我只想要/需要id,这是我的Bar表中的外键。 有没有办法得到福。在没有加载Foo记录的情况下从酒吧获得Id?提前谢谢。

  • 或者(甚至更好)在调用之前以某种方式截取序列化,例如: 我想我可以扩展并重写它的方法,但它被声明为,而且我找不到一种简单的方法来创建的新实例,而不为它提供所有类型元数据细节,这实际上是复制Jackson的一个很好的部分。所以我已经放弃了。 我的问题是-如何定制Jackson的序列化,为特定POJO向JSON输出添加额外的内容,而不引入太多的样板代码,并尽可能多地重用默认的Jackson行为。