Я получаю следующую ошибку при попытке прикрепить объект, который уже прикреплен к данному контексту, через context.AttachTo(...)
:
Объект с таким же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом.
Есть ли способ добиться чего-то вроде:
context.IsAttachedTo(...)
Ура!
Редактировать:
Метод расширения, описанный Джейсоном, близок, но он не работает в моей ситуации.
Я пытаюсь выполнить некоторую работу, используя метод, описанный в ответе на другой вопрос:
Мой код выглядит примерно так:
var user = new User() { Id = 1 };
context.AttachTo("Users", user);
comment.User = user;
context.SaveChanges();
Это отлично работает, за исключением случаев, когда я делаю что-то еще для этого пользователя, когда использую тот же метод и пытаюсь прикрепить фиктивный User
объект. Это не удается, потому что я ранее прикрепил этот фиктивный пользовательский объект. Как я могу это проверить?
источник
(T)entry.Entity
иногда возвращает ноль?T
уже естьIEntityWithKey
, не можете ли вы просто использовать егоentity.EntityKey
свойство, а не восстанавливать его, или вам нужно угадать / предоставитьEntitySetName
?Более простой подход:
bool isDetached = context.Entry(user).State == EntityState.Detached; if (isDetached) context.Users.Attach(user);
источник
.Include()
свойства навигации ed также пытаются прикрепить, когда вы вызываете.Attach
или устанавливаете егоEntityState
значениеEntityState.Unchanged
- и они будут конфликтовать, если какой-либо из объектов ссылается на одно и то же лицо. Я не понял, как присоединить только базовую сущность, поэтому мне пришлось немного переработать проект, чтобы использовать отдельные контексты для каждой «бизнес-транзакции», как это было задумано. Отмечу это для будущих проектов.Попробуйте этот метод расширения (он не протестирован и нестандартный):
public static bool IsAttachedTo(this ObjectContext context, object entity) { if(entity == null) { throw new ArgumentNullException("entity"); } ObjectStateEntry entry; if(context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry)) { return (entry.State != EntityState.Detached); } return false; }
Учитывая ситуацию, которую вы описываете в своем редактировании, вам может потребоваться использовать следующую перегрузку, которая принимает
EntityKey
вместо объекта:public static bool IsAttachedTo(this ObjectContext, EntityKey key) { if(key == null) { throw new ArgumentNullException("key"); } ObjectStateEntry entry; if(context.ObjectStateManager.TryGetObjectStateEntry(key, out entry)) { return (entry.State != EntityState.Detached); } return false; }
Чтобы добиться успеха
EntityKey
в своей ситуации, используйте следующие рекомендации:EntityKey key = new EntityKey("MyEntities.User", "Id", 1);
Вы можете получить
EntityKey
объект из существующего экземпляраUser
с помощью свойстваUser.EntityKey
(из интерфейсаIEntityWithKey
).источник
TryGetObjectStateEntry
которая принимаетEntityKey
вместоobject
. Я отредактировал соответственно. Дайте мне знать, если это не поможет, и мы вернемся к чертежной доске.Используя ключ сущности объекта, который вы пытаетесь проверить:
var entry = context.ObjectStateManager.GetObjectStateEntry("EntityKey"); if (entry.State == EntityState.Detached) { // Do Something }
Доброта,
Дэн
источник
Это не дает прямого ответа на вопрос OP, но именно так я решил свой.
Это для тех, кто использует
DbContext
вместоObjectContext
.public TEntity Retrieve(object primaryKey) { return DbSet.Find(primaryKey); }
Метод DbSet.Find :
По сути, он возвращает прикрепленный объект данного,
primaryKey
поэтому вам просто нужно применить изменения к возвращаемому объекту, чтобы сохранить правильный экземпляр.источник