Общий способ проверки наличия сущности в инфраструктуре 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. Поскольку у сущностей могут быть разные ключи, я не могу их наследовать от общего абзаца с известным ключом для сравнения.
- Невозможно неявно преобразовать тип 'Int' в 'T'
- Стирание Java с общей перегрузкой (не переопределяющей)
- Почему javac жалуется на дженерики, не связанные с аргументами типа classа?
- Каков наилучший способ клонирования / глубокой копии .NET generic Dictionary ?
- Почему я не могу назначить List в List ?
Я мог бы это сделать, но меня беспокоит выполнение исключений извлечения в качестве процесса проверки. Это не работает ни с тех пор, пока объект не отсоединен, свойство 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; } }
- WCF. Сервисные общие методы
- Как сравнить значения родовых типов?
- Как реализовать перечисление с дженериками?
- неявный оператор с использованием интерфейсов
- Почему C # (4.0) не допускает совпадения и контравариантность в типах универсального classа?
- Как преобразовать DataTable в общий список?
- Как я могу получить метод расширения для изменения исходного объекта?
- Генерики, массивы и ClassCastException
Вы хотите, чтобы общий способ проверить, была ли сущность загружена контекстом или общим способом запроса базы данных, если сущность существует?
Для первого случая используйте:
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); }