2016-01-11 5 views
0

Я использую общий репозиторий, и мне нужно добавить дополнительный параметр в один из методов репозитория. Например, у меня есть столбец isDeleted в базе данных, я хочу добавить этот столбец как false в предикат. Как добавить дополнительный параметр в предикат из метода репозитория? Этот дополнительный параметр фиксирован для всех таблиц. (isDeleted = false)Как добавить дополнительный параметр в выражение <Func <T, bool>> предикат в общем репозитории

Это мой оригинальный метод, который получает одну запись из db.

public T GetSingle(Expression<Func<T, bool>> expression) 
{ 
    return _dbSet.Where(expression).SingleOrDefault(); 
} 

Это обновленная версия, чтобы добавить дополнительный параметр, который я дошел до сих пор.

public T GetSingle(Expression<Func<T, bool>> expression) 
{ 
    Expression<Func<T, bool>> extra = d => d.GetType().GetProperty("isDeleted").Equals(false); 
    var exp = Expression.And(expression.Body, extra.Body); 

    var body = Expression.And(expression.Body, extra.Body); 
    var lambda = Expression.Lambda<Func<T, bool>>(body, extra.Parameters); 

    return _dbSet.Where(lambda).SingleOrDefault(); 
} 

Но эта обновленная версия дает лямбда-тело, как это, и из-за этого оно не работает.

((d.ID == value(ProjectName.Namespace.Controllers.ControllerName).User.CompanyId) And d.GetType().GetProperty("isDeleted").Equals(Convert(False))) 
+0

У меня нет кода в руке, однако в прошлом я использовал технику столбца Id на таблицах (где каждая таблица имеет этот столбец/свойство). Я создал интерфейс, содержащийся в 'int Id {set; получить;} '. Затем я добавил этот интерфейс во все определения класса таблицы.В моем коде repostitory я установил ограничение на тип 'T', чтобы сказать, что он должен содержать этот интерфейс. Затем в моем коде я смог вывести свойство Id из моего типа «T». Я знаю, что это звучит странно, но, надеюсь, вы получите суть! –

+0

Я просто не получаю репозитории, подобные этому, EF уже является хранилищем, и все, что им кажется, это сделать жизнь более сложной и удалить функциональность. Например, этот метод не может загружать с помощью Include. Это не так, как реально, вы можете обменять EF на другую технологию с ними. – Mant101

+1

@ Mant101, я в настоящее время работаю над проектом, где EF нужно заменить вызовами веб-службы. Если бы оригинальные разработчики использовали бы репозитории, тогда моя жизнь была бы намного проще. –

ответ

3
public T GetSingle<T>(Expression<Func<T, bool>> expression) 
{ 
    var @params = expression.Parameters; 
    var checkNotDeleted = Expression.Equal(Expression.PropertyOrField(@params[0], "isDeleted"), Expression.Constant(false)); 

    var originalBody = expression.Body; 

    var fullExpr = Expression.And(originalBody, checkNotDeleted); 

    var lambda = Expression.Lambda<Func<T, bool>>(fullExpr, @params); 

    return _dbSet.Where(lambda).SingleOrDefault(); 
} 

После того, как вы начнете использовать методы Expression «s, вам нужно всегда использовать их (за исключением Expression.Constant, конечно). Вся логика и код, который вы пишете, должны быть представлены узлами Expression.

Существует метод PropertyOrField, который считывает значение свойства из определенного выражения. В этом случае мы читаем его из параметра (то есть d => d.isDeleted - мы пишем часть d.isDeleted). Затем нам нужно сравнить значение с ложным.

Наконец, мы просто And оригинальное выражение для нашего и создаем лямбда с исходными параметрами.

+1

Удивительный, чем вы. – Kadir

+0

@ Kadir Извините, я заметил ошибку в логике - это должно быть выражение «Expression.Equal» не «Expression.NotEqual» – Rob

2

Посмотрите PredicateBuilder, в частности, в разделе «Общие предикаты», которая объясняет, как создать общие ограничения для фильтрации элементов

2

Вы можете иметь BaseEntity, который содержит IsDeleted свойства.

Все остальные объекты должны быть дочерними из этого BaseEntity.

В настоящее время в хранилище,

public class Repository<T> where T : BaseEntity 
{ 
.... 
} 

И в запросе, вы можете добавить выражение для IsDeleted также.

Пожалуйста, смотрите здесь: Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle

+0

Это аналогичный метод, описанный в моем комментарии к OP. В моем случае я использовал интерфейс - плюс один tho !! –

0

Вы можете изменить метод:

public T GetSingle(param Expression<Func<T, bool>>[] expression) 

использования массива, и ключевое слово парам.

Чем вы можете отправить два, три, четыре или любое количество параметров, которые вы хотите.

+0

Не полезно. Asker не хочет менять подпись метода. Он хочет, чтобы этот метод проверял вызов 'isDeleted' on * each * без того, чтобы клиент вообще об этом знал. –

+0

О, я вижу. моя вина. – Raskolnikov