Entity Framework Обновление существующего объекта
Я добавил строку в свою базу данных и вернулся с другим контекстом, чтобы обновить его. У меня есть этот класс:
public abstract partial class DataManager<I, C>
where C : class, IDomainObject, I, new( ) where I : IDomainObject
C может быть EntityObject, но этот класс не знает этого.
Мое сохранение выглядит так:
public virtual bool Save( I _item )
{
bool rc = true;
try
{
var set = m_Context.GetObjectSet<I, C>( );
ObjectStateEntry stateEntry = null;
if( ! m_Context.ObjectStateManager.TryGetObjectStateEntry( ( C ) _item, out stateEntry ) )
{
if( _item is EntityObject )
{
if ( _item.IsNew )
{
set.AddObject( ( C ) _item );
}
else
{
try
{
set.Attach( ( C ) _item );
}
catch( Exception ex )
{
set.ApplyCurrentValues( ( C ) _item );
}
и так далее...
В моем тестовом случае stateEntry не найдено TryGetObjectStateEntry. Это, однако, EntityObject, и он не новый (IsNew - мой флаг), поэтому он попадает в другое. Вот моя проблема: set.Attach выдает эту ошибку
"Объект с таким же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом".
и в следующий же момент ApplyCurrentValues выдает это:
"Объект с ключом, который совпадает с ключом предоставленного объекта, не может быть найден в ObjectStateManager. Убедитесь, что значения ключа предоставленного объекта соответствуют значениям ключа объекта, к которому должны применяться изменения".
Как это может быть правдой?
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ:
_item был создан Get в другом контексте. Этот контекст был тогда ликвидирован. На тот момент _item имел EntityState.Unchanged. Я применил некоторые изменения к нему, и он изменился на EntityState.Modified. (Я не ожидал, что, поскольку контекст (и его ObjectStateManager) должен был исчезнуть.) Во всяком случае, когда он достигает Save (выше), его состояние (как сообщается отладчиком) изменяется, но я имею новый контекст к тому времени. Если я получу список ВСЕХ ObjectStateEntries (Добавлено, Удалено, Изменено, Без изменений) на данный момент, их всего два, и _item не является одним из них, как сообщает ApplyCurrentValues, но его нельзя присоединить, потому что "это тоже там! Возможно, проблема в том, что он все еще прикреплен к старому ObjectStateManager (может быть какая-то ссылка, которая не позволяет утилизировать ObjectStateManager?).
2 ответа
Проблема состоит в том, что каждый раз, когда db-контекст инициализируется, он берет строки из базы данных и каждый ряд, назначая ключ сущности. это означает, что одна и та же строка, полученная с помощью 2 db-context, будет иметь 2 разных ключа объекта. ключ объекта подобен идентификатору в структуре объекта и используется вместо идентификатора рассматриваемого объекта. Но ограничения таблиц хотя и сохраняются (без дублирования первичного ключа). Надеюсь, это имеет смысл.
Проблема заключается в том, что вы присоединяете двух разных пользователей к одной и той же организации, однако в каждом случае объект org является отдельным экземпляром.
Если организация уже находится в БД, попробуйте:
Либо задайте для свойств навигации для организации значение NULL и задайте только свойства OrganizationId.
Или загрузите организационную сущность из БД и поместите в нее реквизиты навигации.
Если организации нет в БД:
Используйте тот же экземпляр (выбросьте один и замените его другим).