简体   繁体   English

如何在 Linq 中使用 Dapper

[英]How to use Dapper with Linq

I'm trying to convert from Entity Framework to Dapper to hopefully improve data access performance.我正在尝试从实体框架转换为 Dapper,以期提高数据访问性能。

The queries I use are in the form of predicates like so Expression<Func<TModel, bool>> .我使用的查询采用谓词形式,例如Expression<Func<TModel, bool>>

To give an example:举个例子:

I have the following code which I need to convert to using Dapper.我有以下代码需要转换为使用 Dapper。

What I currently do:我目前在做什么:

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();
}

What I'd like to do:我想做什么:

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

My google-fu is failing me, can someone please assist.我的 google-fu 失败了,有人可以帮忙吗?

Edit:编辑:

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

but I can't seem to figure out how to use it.但我似乎无法弄清楚如何使用它。

Firstly, one of the authors of Dapper said, when someone asked首先,Dapper 的一位作者说,当有人问

Is there a plan to make Dapper.net compatible with IQueryable interfaces?是否有计划使 Dapper.net 与 IQueryable 接口兼容?

that

there are no plans to do this.没有这方面的计划。 It is far far outside what dapper tries to do.这远远超出了 dapper 试图做的事情。 So far that I would say it is antithetical.到目前为止,我会说这是对立的。 Dapper core tries to be the friend to those who love their SQL. Dapper core 试图成为那些喜欢 SQL 的人的朋友。

(see https://stackoverflow.com/a/27588877/3813189 ). (参见https://stackoverflow.com/a/27588877/3813189 )。

In a way, that does suggest that the various extension packages to NuGet may help, as you have suggested.在某种程度上,正如您所建议的那样,这确实表明 NuGet 的各种扩展包可能会有所帮助。

I have tried DapperExtensions , which makes writing the query filters in a programmatic way a little easier - eg.我尝试过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; }
        }
    }
}

I also tried Dapper.Extensions.Linq (the package you suggested), which promises to我也试过Dapper.Extensions.Linq (你建议的包),它承诺

builds on this providing advanced DB access through Linq queries.以此为基础,通过 Linq 查询提供高级数据库访问。 The fluid configuration makes setup simplistic and quick.流体配置使设置简单快捷。

Unfortunately, I also couldn't get very far with it.不幸的是,我也不能走得很远。 There isn't much documentation and the tests don't seem to cover the QueryBuilder, which is what appears to be the class to use to translate Linq Expressions into the Dapper Extensions predicates (as suggested by the issue Parsing boolean expressions with the QueryBuilder ).没有太多文档,并且测试似乎没有涵盖 QueryBuilder,这似乎是用于将 Linq 表达式转换为 Dapper Extensions 谓词的类(如问题Parsing boolean expressions with the QueryBuilder所建议的) . I tried the following, which required add the IEntity interface to my DTO -我尝试了以下操作,这需要将 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; }
        }
    }
}

.. but it failed at runtime with the error .. 但它在运行时失败并出现错误

Operator was not found for StackOverflowAnswer.Program+Products找不到 StackOverflowAnswer.Program+Products 的运算符

I'm not sure why generating the Predicate manually (the first example) works but the QueryBuilder doesn't..我不确定为什么手动生成 Predicate(第一个示例)有效,但 QueryBuilder 没有。

I would say that it's increasingly looking like the comments left on your question are correct, that you will need to re-work your code away from the expressions that you used with Entity Framework.我想说的是,在您的问题上留下的评论越来越看起来是正确的,您将需要重新编写代码,远离与实体框架一起使用的表达式。 Since it's been so difficult to find any information about this QueryBuilder class, I would be concerned that (even if you did get it working) any issues that you encountered would be difficult to get help for (and bugs may go unfixed).由于很难找到关于这个 QueryBuilder 类的任何信息,我会担心(即使你确实让它工作了)你遇到的任何问题都很难获得帮助(并且错误可能无法修复)。

I wrote a utility to work EF with Dapper using attributes.我编写了一个实用程序来使用属性与 Dapper 一起使用 EF。 I parsing predicate and translate to SQL.我解析谓词并转换为 SQL。

"Users" POCO: “用户”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);
        }
    }
}

And simple query:和简单的查询:

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

Maybe it will be useful to you?也许它对你有用?

MicroOrm.Dapper.Repositories MicroOrm.Dapper.Repositories

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM