Общий способ проверки наличия сущности в инфраструктуре Entity?

Как и лучший способ проверить, существует ли объект в Entity Framework?

Я ищу общий способ проверки сущности в DbSet . Что-то вроде этого, что не работает:

 private DbContext DbContext { get; set; } private DbSet DbSet { get; set; } public Boolean Exists(T entity) { return ((from item in this.DbSet where item == entity select item).Count() > 0); } 

Строка, в where item == entity работает в LINQ to SQL, но, по-видимому, не с LINQ to Entities. Поскольку у сущностей могут быть разные ключи, я не могу их наследовать от общего абзаца с известным ключом для сравнения.

Я мог бы это сделать, но меня беспокоит выполнение исключений извлечения в качестве процесса проверки. Это не работает ни с тех пор, пока объект не отсоединен, свойство OriginalValues не может быть получено:

 public Boolean Exists(T entity) { try { var current = this.DbContext.Entry(entity).OriginalValues; // Won't reach this line if the entity isn't in the database yet return true; } catch (Exception ex) { return false; } } 

Вы хотите, чтобы общий способ проверить, была ли сущность загружена контекстом или общим способом запроса базы данных, если сущность существует?

Для первого случая используйте:

 public bool Exists(T entity) where T: class { return this.Set().Local.Any(e => e == entity); } 

В последнем случае используйте (он также проверит загруженные объекты):

 public bool Exists(params object[] keys) { return (this.Set().Find(keys) != null); } 

Редактировать:

EF-код сначала не должен получать доступ к такой информации, но можно получить имя ключей сущностей. Я думаю, что что-то вроде этого должно работать:

 var objContext = ((IObjectContextAdapter)dbContext).ObjectContext; var objSet = objContext.CreateObjectSet(); var keyNames = objSet.EntitySet.ElementType.KeyMembers.Select(m => m.Name); 

Но все это не имеет смысла. Вы хотите использовать общий подход, но ваши сущности не предоставляют необходимую информацию, чтобы обеспечить общий подход. Теперь вы говорите, что даже не знаете ключевых значений. Использование этого «общего» подхода потребует отражения и ручного построения дерева выражений.

Спасибо @Ladislav за то, что он меня в правильном направлении. Вот код для общего метода Exists() .

Я хотел бы отметить, что это не требует отражения и, кажется, работает достаточно хорошо. Единственное, что меня не TryGetObjectByKey() это то, что TryGetObjectByKey() имеет побочный эффект присоединения найденной сущности. Поскольку я не хочу, чтобы Exists() имел этот непреднамеренный результат, мне пришлось отделить объект, если он был найден.

 public Boolean Exists(T entity) { var objContext = ((IObjectContextAdapter)this.DbContext).ObjectContext; var objSet = objContext.CreateObjectSet(); var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entity); Object foundEntity; var exists = objContext.TryGetObjectByKey(entityKey, out foundEntity); // TryGetObjectByKey attaches a found entity // Detach it here to prevent side-effects if (exists) { objContext.Detach(foundEntity); } return (exists); } 
  • Выражение lambda и общий метод
  • Объяснение обобщенного <T extends Comparable > в коллекции.sort / сопоставимый код?
  • Общий метод всех элементов управления
  • Что означает (угловые скобки) в Java?
  • Возврат ограниченных генериков из функций и методов
  • Нельзя ли динамически использовать Generics?
  • Объяснение принципа get-put
  • Можно использовать тип Nullable как общий параметр?
  • Использование ключевого слова «params» для общих параметров в C #
  • Ограничение дженериков с помощью ключевого слова 'super'
  • Тип стирания, переопределение и дженерики
  • Давайте будем гением компьютера.