如何使用Dqper与Linq

Ria*_*ert 8 c# linq expression predicate dapper

我正在尝试从实体框架转换为Dapper,以期提高数据访问性能.

我使用的查询是谓词形式,如"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();
}
Run Code Online (Sandbox Code Playgroud)

我想做什么:

public async Task<List<TModel>> Get(Expression<Func<TModel, bool>> query)
{
    using (IDbConnection cn = this.GetConnection)
    {
        return await cn.QueryAsync<TModel>(query);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的google-fu让我失望,有人可以帮忙.

编辑:

请注意,我找到了:https: //github.com/ryanwatson/Dapper.Extensions.Linq

但我似乎无法弄清楚如何使用它.

Dan*_*rts 16

首先,Dapper的一位作者说,有人问

是否有计划使Dapper.net与IQueryable接口兼容?

没有计划这样做.它远不及小巧玲珑的尝试.到目前为止,我认为它是对立的.Dapper核心试图成为那些喜欢他们的SQL的朋友.

(参见/sf/answers/1931221421/).

在某种程度上,这确实表明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; }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我也尝试过Dapper.Extensions.Linq(你建议的软件包)

以此为基础,通过Linq查询提供高级数据库访问.流体配置使设置简单快捷.

不幸的是,我也离不开它.没有太多的文档,测试似乎没有涵盖QueryBuilder,这似乎是用于将Linq表达式转换为Dapper Extensions谓词的类(正如使用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; }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

..但它在运行时因错误而失败

未找到StackOverflowAnswer.Program + Products的运算符

我不确定为什么手动生成谓词(第一个例子)有效但QueryBuilder没有...

我会说,你的问题上留下的评论越来越正确,你需要重新使用你在Entity Framework中使用的表达式.由于很难找到关于这个QueryBuilder类的任何信息,我会担心(即使你确实让它工作)你遇到的任何问题都很难获得帮助(而且bug可能会不复存在).

  • 感谢您抽出时间来研究我的问题。我很高兴(也很伤心)有人得出了与我相同的结论。非常感谢。 (2认同)
  • 只是添加到此。尽管Dapper的作者可能将LINQ扩展视为Dapper与其预期目的“相对”的扩展,但我确实相信这样的事情有充分的理由和好处。首先,此类库提供了针对sql注入攻击的内置保护。其次,您可以获得智能感知的好处。您将获得所有这些信息以及Dapper的稳定性和可靠性,而无需考虑实体框架的大量抽象,警告和开销。手工编写纯SQL并不总是选择Dapper作为ORM的决定因素。 (2认同)

Ser*_*e K 9

我写了一个实用程序来使用属性与Dapper一起工作EF.我解析谓词并转换为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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

简单查询:

using (var cn = new SqlConnection("..."))
{
    var usersRepository = new DapperRepository<User>(cn)
    var allUsers = await userRepository.FindAllAsync(x => x.AccountId == 3 && x.Status != UserStatus.Deleted);
}
Run Code Online (Sandbox Code Playgroud)

也许它会对你有用吗?

MicroOrm.Dapper.Repositories

  • 我知道您的回复不是原始问题的答案,因为您没有使用LINQ.但是,您的解决方案是最接近任何人在不使用Entity Framework的情况下获得类型安全的进程外查询表达式的解决方案.惊人!做得好! (4认同)