Селфрекинг сущностей, прикрепите только саму сущность без ссылок
Используя: SQL Server 2008 R2, Entityframework 4.3.1
мой сценарий: я читаю свои объекты из базы данных на стороне обслуживания. Я использую шаблон T4 "Селфрекинг-сущности" для создания объектов из объектного контекста. Эти объекты доставляются клиенту, где ими манипулируют, и отправляют обратно в службу.
С помощью самообследования я могу видеть, какие свойства были изменены на стороне клиента.
Мой метод обновления сущности выглядит так:
using ( var transaction = new TransactionScope() )
{
var connection = this.ConnectionManager.GetConnectionstring( AcademyOne.Models.Connection.A1Databases.A1VerwaltungEntity );
using ( var context = new istis.AcademyOne.Models.Models.A1Verwaltung.VerwaltungModelsContext( connection.Connectionstring ) )
{
foreach ( var seminar in seminare )
{
context.Seminar.Attach( seminar );
context.ObjectStateManager.ChangeObjectState( seminar, StateValueConverter.GetEquivalentEntityState( seminar.ChangeTracker.State ) );
}
context.SaveChanges( SaveOptions.DetectChangesBeforeSave );
}
transaction.Complete();
}
Моя проблема. Субъект "Семинар" имеет ссылку на "Дозент". Может быть несколько семинаров, имеющих ссылку на один и тот же объект Dozentobject. Поэтому, когда я присоединяю оба семинара с одной и той же ссылкой, я получаю следующее исключение:
Объект с таким же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом
Любые идеи, как я могу решить эту проблему? Есть ли возможность прикрепить только простой объект без ссылки, но включая идентификатор ForeignKey? Любые другие подходы я могу попробовать?
2 ответа
Решил мою проблему с помощью своего рода грязного обходного пути. Я вставляю / обновляю теперь каждый элемент по-своему, и теперь он работает. Надеялся на пакетное обновление, но это не представляется возможным.
Все равно спасибо за вашу работу
У вашего кода есть некоторые проблемы. Прежде всего, если вы используете Self Tracking Entities, вам не нужно менять состояние службы отслеживания изменений в службе. Поскольку сущности с самопроверкой имеют свое собственное состояние, если вы попытаетесь сохранить какой-либо объект, контекст выполнит соответствующее действие в соответствии с состоянием отслеживания объекта. Таким образом, только присоединение обновленного объекта и вызов сохраненных изменений достаточно для сохранения объекта.
using ( var transaction = new TransactionScope() )
{
var connection = this.ConnectionManager.GetConnectionstring( AcademyOne.Models.Connection.A1Databases.A1VerwaltungEntity );
using ( var context = new istis.AcademyOne.Models.Models.A1Verwaltung.VerwaltungModelsContext( connection.Connectionstring ) )
{
foreach ( var seminar in seminare )
{
//The following line shall be commented out
//context.Seminar.Attach( seminar );
context.Seminar.ApplyChanges( seminar );
//The following line shall be commented out.
//context.ObjectStateManager.ChangeObjectState( seminar, StateValueConverter.GetEquivalentEntityState( seminar.ChangeTracker.State ) );
}
context.SaveChanges( SaveOptions.DetectChangesBeforeSave );
}
transaction.Complete();
}
Во-вторых, я думаю, что эта проблема возникает из-за того, что создается состояние Dozent. Таким образом, когда вы вызываете метод присоединения для каждой обновленной сущности Семинара, новая сущность Dozent присоединяется к контексту объекта (фактически разные объекты с одинаковым идентификатором); что приводит к нарушению первичного ключа.
Чтобы решить эту проблему, вместо отправки списка семинаров, отправьте объект, который имеет отношение один ко многим с объектами семинара (конечно, если у вас есть такой объект).
Или, если у вас нет родительской сущности, попробуйте установить значения внешнего ключа сущностей семинара, не устанавливая связанное свойство навигации Dozent. Сначала вы должны убедиться, что свойства внешнего ключа существуют в файле модели EDMX.