Учитывая схему базы данных с двумя таблицами: Company
и Employee
, где Employee
таблица имеет внешний ключ к Company
таблице, что правильный код, чтобы изменить компанию конкретный работник, связанный с ?правильный путь, чтобы изменить Entity Framework отношения
Метод 1:
company1.Employees.Remove(employee);
company2.Employees.Add(employee);
Проблема:
Это, кажется, работает, но ужасно неэффективен в качестве ссылки на
company1.Employees
нагрузки всех сотрудников дляcompany1
, и ссылка доcompany2.Employees
загружает всех сотрудников наcompany2
.
Способ 2:
employee.Company = company2;
Проблема:
Вызывает исключение: Кратность ограничение нарушается. Роль «Компании» отношений «XXX.FK_Employee_Companies» имеет множественность 1 или 0..1.
Метод 3:
employee.CompanyId = company2.Id;
Проблема:
Для меня это не меняет значение
CompanyId
столбца в базе данных. Он по-прежнему имеет значение, которое было ранее.
Я работаю с хорошо протестированного кода в большом приложении, которое использует мой метод 1 и я стараюсь, чтобы оптимизировать его после того, как проблемы с производительностью были найдены. Я понимаю, что могут быть другие факторы, которые влияют на результаты, которые я получаю. Я ищу кого-то с более глубоким пониманием внутренней работы Entity Framework, чтобы предложить, как они подходят к этому.
EDIT:
Я теперь был сказан более чем одним человеком, что мой Метод 1 не нагружают все связанные сотрудник. Но я выполнил несколько тестов на этом, которые показывают, что это так. Я даже создал простое тестовое приложение. Вот мой код.
var website = context.Websites.FirstOrDefault();
var ranking = website.Rankings.FirstOrDefault();
Кажется, что некоторые люди предполагают, что вторая линия будет загружать только одну строку из Rankings
таблицы.Однако, здесь запросы, генерируемые:
SELECT TOP (1)
[c].[ID] AS [ID],
[c].[Title] AS [Title],
[c].[URL] AS [URL],
[c].[AliasForID] AS [AliasForID],
[c].[ActiveState] AS [ActiveState],
[c].[Alert] AS [Alert]
FROM [dbo].[Website] AS [c]
И:
exec sp_executesql N'SELECT
[Extent1].[ID] AS [ID],
[Extent1].[WebsiteID] AS [WebsiteID],
[Extent1].[PageRank] AS [PageRank],
[Extent1].[AlexaRank] AS [AlexaRank],
[Extent1].[AlexaReach] AS [AlexaReach],
[Extent1].[DateAdded] AS [DateAdded]
FROM [dbo].[Ranking] AS [Extent1]
WHERE [Extent1].[WebsiteID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1
Обратите внимание на второй запрос. Он возвращает все строки из таблицы Ranking
, которые связаны с объектом Website
. Он не фильтрует, чтобы возвращать только первую строку. Точно так же доступ к для вызова метода Add()
будет загружать всех сотрудников, связанных с company1
, поскольку Website.Rankings
имеет тип ICollection<>
, а не IQueryable<>
.
Ленивая нагрузка абсолютно не связана. Ленивая загрузка просто означает, что коллекция не загружается, пока код не ссылается на эту коллекцию (или любое другое свойство, которое ссылается на данные из связанной таблицы). Но как только код ссылается на эту коллекцию, все связанные объекты загружаются.
Я хотел бы, чтобы кто-то показал мне, как это неверно или как предотвратить это. Пока что единственные люди, которые говорят это, неверны, не желают поддерживать это и/или просто оскорблять меня, когда я попросил их поддержать их требования. Непонимание того, как это работает, может привести к серьезным проблемам с производительностью.
Комментарии не для широкого обсуждения; этот разговор был [перемещен в чат] (http://chat.stackoverflow.com/rooms/91230/discussion-on-question-by-jonathan-wood-correct-way-to-change-entity-framework-r) , –