Какой самый разумный способ узнать, привязана ли сущность к dbContext или нет?
когда я пытаюсь привязать объект к контексту, я получаю исключение
Объект с тем же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом
Это ожидаемое поведение.
Но я хотел бы знать, как это знает ObjectStateManager?
Я хотел бы сделать эту проверку самостоятельно, прежде чем
Ответы
Ответ 1
Если вы используете DbContext API (вы упомянули ef-code-first), вы можете просто использовать:
context.YourEntities.Local.Any(e => e.Id == id);
или более сложный
context.ChangeTracker.Entries<YourEntity>().Any(e => e.Entity.Id == id);
В случае ObjectContext API вы можете использовать:
context.ObjectStateManager.GetObjectStateEntries(~EntityState.Detached)
.Where(e => !e.IsRelationship)
.Select(e => e.Entity)
.OfType<YourEntity>()
.Any(x => x.Id == id);
Ответ 2
Здесь используется метод расширения для получения объекта из контекста, не беспокоясь о том, что он уже прикреплен:
public static T GetLocalOrAttach<T>(this DbSet<T> collection, Func<T, bool> searchLocalQuery, Func<T> getAttachItem) where T : class
{
T localEntity = collection.Local.FirstOrDefault(searchLocalQuery);
if (localEntity == null)
{
localEntity = getAttachItem();
collection.Attach(localEntity);
}
return localEntity;
}
Просто позвоните:
UserProfile user = dbContext.UserProfiles.GetLocalOrAttach<UserProfile>(u => u.UserId == userId, () => new UserProfile { UserId = userId });
Ответ 3
проверить
entity.EntityState == System.Data.EntityState.Detached
перед прикреплением
Ответ 4
Обратите внимание, что если отслеживание изменений отключено в вашем контексте, запрос ObjectStateManager
или ChangeTracker
может вернуть, что объект не находится в ObjectContext
, даже если он на самом деле уже там. Поэтому, если вы попытаетесь прикрепить такой объект, это вызовет исключение.
context.Set<T>.Local.Any(e => e.Id == id);
работает событие, если отслеживание изменений отключено.
если вы не знаете тип объекта, существует различный подход, либо вы определяете метод с использованием отражения, либо другие методы, подобные этому
int GetIdOf(object entity){...}
Или вы определяете интерфейс, используемый вашими классами, например
public interface IMyEntity
{
int Id{get;set;}
}
и использовать его следующим образом:
context.Set(e.GetType()).Local.Cast<IMyEntity>().Any(e => e.Id == id);
Ответ 5
вы можете запросить dbContext с помощью метода расширения "Любой":
bool alreadyInDB = dbContext.Entity.Where(a=>a.ID==myEntity.id).Any();