实体框架维护多个插入的外键

我继承了一个包含3个表的简单数据库。

董事会表:BoardID,BoardName 城市表:CityID,CityName,BoardID 子表:ChildID,ChildName,CityID,BoardID

所有ID字段均已打开身份插入。

当我插入时,

我要先插入局中,保存更改,将ID插入“城市表”,保存更改,然后最后将两个ID插入子表并保存更改。

有没有办法在上下文中保持此状态并立即保存更改?

tftp156656 回答:实体框架维护多个插入的外键

是的,首先阅读导航属性和与EF的映射关系。使用这些关系,EF将跟踪哪些实体依赖于另一个实体,以便您可以像以下那样创建实体图:

using ( var context = new MyContext())
{
    var newBoard = new Board { BoardName = boardName };
    var newCity = new City { CityName = cityName,Board = newBoard };
    var newChild = new Child { ChildName = childName,City = newCity };
    context.Children.Add(newChild);
    context.SaveChanges();
}

当EF提交更改时,映射到标识列的每个实体都将获得其新ID,并且这些ID将自动分配给关联实体的FK。

使用EF,您也不需要在实体中公开FK字段,建议避免公开FK。借助EF Core,您可以使用Shadow Properties来映射您的实体。暴露FK可能导致更新时出现问题。如果孩子公开了城市参考和CityId FK属性,而我想给孩子分配一个新城市,那么我现在有两种方法:

child.City = fourthCity;
// or 
child.CityId = 4;

这可能导致不一致的行为和错误假设周围的错误。例如:

var child = context.Children.Find(1); // Child #1 references City #1.
var fourthCity = context.Cities.Find(4);

child.City = fourthCity;
Console.WriteLine(child.City.CityId); // "4"
Console.WriteLine(child.CityId); // "1" 
context.SaveChanges();
Console.WriteLine(child.CityId); // Now it's "4" 

SaveChanges之前引用FK的任何代码都将获得旧ID,而引用相关实体ID的代码将获得新ID。在调用SaveChanges之前,不会更新FK。

更改FK也会导致问题和错误。

var child = context.Children.Find(1); // Child #1 references City #1.

child.CityId = 4;
Console.WriteLine(child.CityId); // "4" 
Console.WriteLine(child.City.CityId); // NullReferenceException! (Lazy load call fails)

如果尝试这样做,则延迟加载(至少在EF6中如此)会晃动。如果您渴望加载城市:

var child = context.Children.Include(x => x.City).Single(x => x.ChildId == 1); // Child #1 references City #1.

child.CityId = 4;
Console.WriteLine(child.CityId); // "4" 
Console.WriteLine(child.City.CityId); // "1"
Context.SaveChanges();
Console.WriteLine(child.City.CityId); // "4"

当代码引用FK与导航属性时,您将遇到不一致的行为。在某些情况下,您可能希望实体公开FK而不是导航属性(例如,在执行大容量操作时),因此我建议您使用其中之一,而不要同时使用两者。

此外,请避免对架构进行非规范化。如果某个子级与一个城市相关联,而一个城市与一个理事会相关联,则可以通过其城市引用该子级的理事会,而不是在该子级上具有BoardID。

child.City.Board.BoardName

非规范化是有问题的,因为无法强制儿童的董事会参考将与其分配的市议会参考相匹配。

例如:

var board1 = context.Boards.Find(1);
var board2 = context.Boards.Find(2);
var child = context.Children.Find(1);

如果子ID#1引用了城市ID#1,而该ID则引用了委员会ID#1,并且子孩子也引用了ID#1,则代码中的此类内容(故意或错误地)可能会导致问题。路:

child.Board = board2;

任何通过child.Board.BoardId引用儿童板的代码都将返回“ 2”,但是任何引用child.City.Board.BoardId的代码仍将返回“ 1”。与在实体上公开FK的问题类似,这些归一化的引用可能会根据您的外观而导致引用错误,除了FK问题不同,提交更改后这些引用不会自动解决。儿童的板卡ID及其所引用城市的板卡ID在数据中不同步。

本文链接:https://www.f2er.com/3157245.html

大家都在问