如何将 Dapper 与 Linq 一起使用

How to use Dapper with Linq

我正在尝试从 Entity Framework 转换为 Dapper,希望能提高数据访问性能。

我使用的查询是像这样的谓词形式Expression<Func<TModel, bool>>

举个例子:

我有以下代码需要转换为使用 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 让我失望了,有人可以帮忙吗。

编辑:

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

但我似乎不知道如何使用它。

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

Is there a plan to make Dapper.net compatible with IQueryable interfaces?

那个

there are no plans to do this. It is far far outside what dapper tries to do. So far that I would say it is antithetical. Dapper core tries to be the friend to those who love their SQL.

(参见 )。

在某种程度上,这确实表明 NuGet 的各种扩展包可能会有所帮助,正如您所建议的那样。

我试过 DapperExtensions,这使得以编程方式编写查询过滤器更容易一些 - 例如。

using System.Data.SqlClient;
using DapperExtensions;

namespace WhosebugAnswer
{
    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; }
        }
    }
}

我也尝试了 Dapper.Extensions.Linq(你建议的包),它承诺

builds on this providing advanced DB access through Linq queries. The fluid configuration makes setup simplistic and quick.

不幸的是,我也无法深入了解它。没有太多文档,测试似乎没有涵盖 QueryBuilder,这似乎是 class 用于将 Linq 表达式转换为 Dapper 扩展谓词的东西(如问题 [=19 所建议的那样) =]).我尝试了以下操作,这需要将 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 WhosebugAnswer
{
    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; }
        }
    }
}

.. 但它在运行时失败并出现错误

Operator was not found for WhosebugAnswer.Program+Products

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

我想说的是,您的问题上留下的评论看起来越来越正确,您将需要重新编写代码,远离您在 Entity Framework 中使用的表达式。由于很难找到有关此 QueryBuilder class 的任何信息,我担心(即使你确实让它工作)你遇到的任何问题都很难获得帮助(并且错误可能未修复) ).

我编写了一个实用程序来使用属性将 EF 与 Dapper 一起使用。我解析谓词并翻译成 SQL.

"Users" 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);
}

也许它对你有用?

MicroOrm.Dapper.Repositories