Либо LINQ to SQL, либо LINQ to Entities уже имеют возможность конвертировать LINQ в текстовую строку SQL. Но я хочу, чтобы мое приложение выполняло преобразование без использования контекста db, что, в свою очередь, означает активное соединение с базой данных, которое требуется обоим этим провайдерам.
Я хотел бы преобразовать выражение LINQ в эквивалентную строку SQL для предложений WHERE
и ORDER BY
, без зависимости от контекста БД, чтобы сделать следующий интерфейс репозитория:
public interface IStore<T> where T : class
{
void Add(T item);
void Remove(T item);
void Update(T item);
T FindByID(Guid id);
//sure could use a LINQ to SQL converter!
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
IEnumerable<T> FindAll();
}
Вопрос
Это прежде всего обход дерева и преобразование, которое меня интересует. Кто-нибудь знает о существующей библиотеке (nuget?), которую я могу включить для использования в таком настраиваемом контексте?
Как я уже создал свой собственный рабочий инструмент LINQ, преобразованный в текст SQL, аналогично этому дереву выражений к примеру SQL который работает в моем выше хранилище. Это позволяет мне писать код следующим образом:
IRepository<Person> repo = new PersonRepository();
var maxWeight = 170;
var results = repo.Find(x => (x.Age > 40 || x.Age < 20) && x.Weight < maxWeight);
Но мой код и этот пример являются примитивными (и этот пример сам полагается на контекст db LINQ to SQL). Например, не обрабатывать генерацию операторов "LIKE".
Я не ожидаю и не нуждаюсь в генератор-инструменте, который обрабатывает каждый мыслимый запрос LINQ. Например, я не беспокоюсь о том, как обрабатывать и генерировать объединения или включать. Фактически, с другими ~ 20 часами мой собственный пользовательский код может охватывать все случаи, о которых я беспокоюсь (в основном, инструкции "WHERE" и "ORDER BY" ).
Но в то же время я чувствую, что мне не нужно писать собственный код для этого. Если я застрял писать свои собственные, то мне все равно будет интересно, если кто-то может указать мне на определенные классы, которые я могу отразить и подражать (NHibernate, EF и т.д.). Я спрашиваю о том, какие конкретные классы заглядывают, если вы их знаете, потому что я не хочу часами просеивать код массивного инструмента, чтобы найти нужную мне часть.
Не важно, но если кто-то хочет знать, почему я не просто использую LINQ to SQL или LINQ для Entities... для моего конкретного приложения я просто предпочитаю использовать такой инструмент, как Dapper.
ИСПОЛЬЗОВАНИЕ CASES Независимо от того, завершу ли я сам инструмент или найду стороннюю библиотеку, вот почему полезно использовать "текстовую строку LINQ to SQL":
- Тип предиката я в метод
IRepository.Find
имеет intellisense и базовую проверку времени компиляции. - Мой предлагаемый интерфейс IStore может быть реализован для доступа к БД или доступа к веб-сервисам. Чтобы уточнить, если я могу преобразовать предикат LINQ "WHERE/ORDER BY" в предложение SQL "WHERE/ORDER BY", то...
- Строка SQL может использоваться непосредственно Dapper.
- Строка SQL, в отличие от выражения LINQ, может быть отправлена в службу WCF, которая будет использоваться для прямого доступа к БД (который сам по себе не может использовать Dapper).
- Строка SQL может быть десериализована, с настраиваемый код, обратно в оператор LINQ службой WCF. Эрик Липперт комментирует это.
- Пользовательский интерфейс может использовать механику IQueryable для динамического создания предиката для предоставления репозиторию
Короче говоря, такой инструмент помогает реализовать понятие хранилища "спецификация" или "запрос объекта" в соответствии с DDD и делает это, не принимая зависимость от EF или LINQ to SQL.