Как использовать Dapper с Linq
Я пытаюсь преобразовать из Entity Framework в Dapper, чтобы, надеюсь, повысить производительность доступа к данным.
запросы, которые я использую, имеют форму предикатов типа so " Expression>".
приведу пример:
у меня есть следующий код, который мне нужно преобразовать в использование Dapper.
что я сейчас делаю:
public async Task<List<TModel>> Get(Expression<Func<TModel, bool>> query)
{
// this.Context is of type DbContext
return await this.Context.Set<TModel>().Where(query).ToListAsync();
}
что я хотел бы сделать:
public async Task<List<TModel>> Get(Expression<Func<TModel, bool>> query)
{
using (IDbConnection cn = this.GetConnection)
{
return await cn.QueryAsync<TModel>(query);
}
}
мой google-fu подводит меня, может кто-то, пожалуйста помогать.
Edit:
обратите внимание, что я нашел: https://github.com/ryanwatson/Dapper.Extensions.Linq
но я не могу понять, как его использовать.
2 ответов
во-первых, один из авторов Dapper сказал, когда кто-то спросил
есть ли план, чтобы сделать Dapper.net совместимость с интерфейсами IQueryable?
это
нет никаких планов, чтобы сделать это. Это далеко за пределами того, что пытается сделать щеголь. Пока что я бы сказал, что это противоречит. Dapper core пытается быть другом для тех, кто любит свой SQL.
(см. https://stackoverflow.com/a/27588877/3813189).
таким образом, это предполагает, что различные пакеты расширений для NuGet могут помочь, как вы предложили.
Я пробовал DapperExtensions, что делает написание фильтров запросов программным способом немного проще-например.
using System.Data.SqlClient;
using DapperExtensions;
namespace StackOverflowAnswer
{
class Program
{
static void Main(string[] args)
{
using (var cn = new SqlConnection("Server=.;Database=NORTHWND;Trusted_Connection=True;"))
{
var list = cn.GetList<Products>(
Predicates.Field<Products>(f => f.Discontinued, Operator.Eq, false)
);
}
}
class Products
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public bool Discontinued { get; set; }
}
}
}
Я тоже пробовал щеголь.Увеличение.В LINQ (пакет, который вы предложили), который обещает
строит на этом предоставление расширенного доступа к БД через Linq-запросы. Жидкая конфигурация делает установку упрощенным и быстрым.
к сожалению, я также не мог получить очень далеко. Существует не так много документации, и тесты, похоже, не охватывают QueryBuilder, который, по-видимому, является классом для перевода выражений Linq в предикаты расширений Dapper (как предложено проблемой разбор логических выражений с помощью QueryBuilder). Я попытался следующее, что требуется добавить интерфейс IEntity в мой DTO -
using System;
using System.Data.SqlClient;
using System.Linq.Expressions;
using Dapper.Extensions.Linq.Builder;
using Dapper.Extensions.Linq.Core;
using DapperExtensions;
namespace StackOverflowAnswer
{
class Program
{
static void Main(string[] args)
{
using (var cn = new SqlConnection("Server=.;Database=NORTHWND;Trusted_Connection=True;"))
{
Expression<Func<Products, bool>> filter = p => !p.Discontinued;
var queryFilter = QueryBuilder<Products>.FromExpression(filter);
var list = cn.GetList<Products>(
queryFilter
);
}
}
class Products : IEntity
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public bool Discontinued { get; set; }
}
}
}
.. но это не удалось во время выполнения с ошибкой
оператор не найден для StackOverflowAnswer.Программа + Продукты
Я не уверен, почему создание предиката вручную (первый пример) работает, но QueryBuilder этого не делает..
Я бы сказал, что все больше похоже, что комментарии, оставленные на ваш вопрос, верны, что вам нужно будет повторно обработайте код от выражений, которые вы использовали с Entity Framework. Поскольку было так сложно найти какую-либо информацию об этом классе QueryBuilder, я был бы обеспокоен тем, что (даже если вы его заработали) любые проблемы, с которыми вы столкнулись, будет трудно получить помощь (и ошибки могут быть незафиксированными).
Я написал утилиту для работы EF с Dapper, используя атрибуты. Я разбираю предикат и переводю на SQL.
"пользователи" POCO:
[Table("Users")]
public class User
{
[Key]
[Identity]
public int Id { get; set; }
public string Login { get; set;}
[Column("FName")]
public string FirstName { get; set; }
[Column("LName")]
public string LastName { get; set; }
public string Email { get; set; }
[NotMapped]
public string FullName
{
get
{
return string.Format("{0} {1}", FirstName, LastName);
}
}
}
и простой запрос:
using (var cn = new SqlConnection("..."))
{
var usersRepository = new DapperRepository<User>(cn)
var allUsers = await userRepository.FindAllAsync(x => x.AccountId == 3 && x.Status != UserStatus.Deleted);
}
может быть, это будет полезным для вас?