Можно ли проверить, если объект уже присоединен к контексту данных в Entity Framework?
Я получаю следующую ошибку при попытке прикрепить объект, который уже прикреплен к данному контексту через context.AttachTo(...):
объект с тем же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом.
есть ли способ достичь чего-то вдоль линий оф:
context.IsAttachedTo(...)
Ура!
Edit:
метод расширения, описанный Джейсоном, близок, но он не работает для моей ситуации.
Я пытаюсь сделать некоторую работу, используя метод, описанный в ответе на другой вопрос:
мой код выглядит как это:
var user = new User() { Id = 1 };
context.AttachTo("Users", user);
comment.User = user;
context.SaveChanges();
это работает нормально, за исключением тех случаев, когда я делаю что-то еще для этого пользователя, где я использую тот же метод и пытаюсь прикрепить манекен User "объект". Это не удается, потому что я ранее прикрепил этот фиктивный объект пользователя. Как я могу это проверить?
5 ответов:
вот что я в конечном итоге, который работает очень хорошо:
public static void AttachToOrGet<T>(this ObjectContext context, string entitySetName, ref T entity) where T : IEntityWithKey { ObjectStateEntry entry; // Track whether we need to perform an attach bool attach = false; if ( context.ObjectStateManager.TryGetObjectStateEntry ( context.CreateEntityKey(entitySetName, entity), out entry ) ) { // Re-attach if necessary attach = entry.State == EntityState.Detached; // Get the discovered entity to the ref entity = (T)entry.Entity; } else { // Attach for the first time attach = true; } if (attach) context.AttachTo(entitySetName, entity); }вы можете назвать это следующим образом:
User user = new User() { Id = 1 }; II.AttachToOrGet<Users>("Users", ref user);это работает очень хорошо, потому что это как
context.AttachTo(...)кроме того, вы можете использовать идентификатор трюк я процитировал выше каждый раз. В конечном итоге вы получаете либо ранее прикрепленный объект, либо свой собственный объект. ЗвонюCreateEntityKeyв контексте убедитесь, что он хороший и общий и будет работать даже с составными ключами без дальнейшего кодирования (потому что EF уже может сделай это для нас!).
более простой подход:
bool isDetached = context.Entry(user).State == EntityState.Detached; if (isDetached) context.Users.Attach(user);
попробуйте этот метод расширения (это непроверенный и вне манжеты):
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).
используя ключ сущности объекта, который вы пытаетесь проверить:
var entry = context.ObjectStateManager.GetObjectStateEntry("EntityKey"); if (entry.State == EntityState.Detached) { // Do Something }доброжелательность,
Дэн
это не дает прямого ответа на вопрос OPs, но вот как я решил свой.
это для тех, кто использует
DbContextвместоObjectContext.public TEntity Retrieve(object primaryKey) { return DbSet.Find(primaryKey); }DbSet.Найти Метод:
находит объект с заданными значениями первичного ключа. Если сущность с заданные значения первичного ключа существуют в контексте, то это тут же вернулся не сделав запрос в магазин. Иначе, запрос в магазин для сущность с заданным первичным объектом Ключевые значения и эта сущность, если она найдена, присоединяется к контексту и возвращенный. Если ни одна сущность не найдена в контексте или хранилище, то null возвращенный.
в принципе, он возвращает вложенный объект данного
primaryKeyпоэтому вам просто нужно применить изменения к возвращаемому объекту, чтобы сохранить правильный экземпляр.
Comments