Entity Framework поддерживает внешний ключ для нескольких вставок - PullRequest
0 голосов
/ 05 ноября 2019

Я унаследовал простую базу данных с 3 таблицами.

Board Board: BoardID, BoardName City Таблица: CityID, CityName, BoardID Дочерняя таблица: ChildID, ChildName, CityID, BoardID

Вседля полей идентификаторов включена вставка идентификатора.

Когда я выполняю вставки,

я сначала вставляю в Board, сохраняю изменения, вставляю ID в таблицу городов, сохраняю изменения и, наконец, вставляю обаИдентификаторы в дочерней таблице и сохранение изменений.

Есть ли способ сохранить это в контексте и сохранить изменения сразу?

1 Ответ

1 голос
/ 06 ноября 2019

Да, начните с чтения свойств навигации и сопоставления отношений с 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 перейдет к фиксации изменений, каждая сущность, сопоставленная со столбцом идентичности, получит свойновый идентификатор, и эти идентификаторы будут автоматически назначаться для 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" 

Любой код, ссылающийся на FK до SaveChanges, получит старый идентификатор, а код, ссылающийся на идентификатор связанного объекта, получит новый. FK не обновляется до тех пор, пока не будет вызван SaveChanges.

Изменение 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);

Если идентификатор ребенка № 1 ссылается на идентификатор города №1, которая ссылается на Идентификатор платы № 1, а Child также имеет ссылку на Идентификатор платы № 1, тогда что-то подобное в коде, преднамеренное или по ошибке, может вызвать проблемы в будущем:

child.Board = board2;

Любойкод, ссылающийся на доску ребенка через child.Board.BoardId, будет возвращать "2", однако любой код, который ссылается на child.City.Board.BoardId, все равно будет возвращать "1". Подобно проблеме с раскрытием FK на ваших сущностях, эти денормализованные ссылки могут привести к неправильным ссылкам в зависимости от того, куда вы смотрите, за исключением того, что в отличие от проблемы FK, они не разрешаются автоматически при фиксации изменений. Идентификатор доски ребенка и идентификатор доски города, на который она ссылается, не совпадают в данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...