如何有效地将EF linq查询迁移到Dapper?

时间:2017-07-27 03:39:56

标签: entity-framework dapper query-performance

我正在尝试将EF迁移到Dapper,我正在寻找一种更好,更有效的方法来迁移现有的linq表达式“IQueryable”以使用Dapper。

例如:

public class MyDbContext : DbContext
{
    public DbSet<MyEntity> MyEntity { get; set; }
    +20 more entities..
}

// Inside repository
using (var context = new MyDbContext())
{
     context.MyEntity.Where( x => x.Id == 1) // How can I easily migrate this linq to Dapper?
}

上面的代码只是我正在尝试迁移的一个简单示例。其中一些查询是简单和复杂的混合。目前,我在MyDbContext中有20多个存储库和20多个DbSet,它们在存储库中使用了这种方法。

我在互联网上搜索,但我找不到更好的方法。到目前为止,唯一的方法是将linq逐个转换为查询字符串并在Dapper中使用它。这是可行但繁琐和巨大的努力。性能是我为什么要迁移到Dapper的最大问题。

有没有人比我现在想的更好的方法呢?

2 个答案:

答案 0 :(得分:1)

我找到了解决自己问题的药。我允许传递谓词并创建类似于现有的Linq函数,而不是拦截查询。

public class QueryLinq
{
    private readonly IDatabase _database;
    public QueryLinq(IDatabase database)
    {
        _database = database; // Dapper implementation
    }

    public IEnumberable<T> Where<T>(Func<T,bool> predicate)
    {
        var enumerable = _database.Query<T>();
        return enumerable(predicate);
    }
}

// Existing Repository
public class MyRepository
{
    private readonly QueryLinq _queryLinq;
    public MyRepository(QueryLinq queryLinq)
    {
       _queryLinq = queryLinq;
    }

    public IEnumerable<MyEntity> SelectMyEntity()
    {
        // Before
        // using (var context = new MyDbContext())
        // {            
        //    context.MyEntity.Where( x => x.Id == 1);
        // }

        // Now
        return _queryLinq.Where<MyEntity>( x => x.Id == 1);
    }
}

在这种方法中,我不需要担心现有的查询。

更新8/16/2018:有关此方法的完整详情,请访问here

答案 1 :(得分:0)

您可以使用Entity Framework Logging将生成的SQL输出到Visual Studio控制台。它就像添加:

一样简单
_context.Database.Log = x => Trace.WriteLine(x);

到您的服务或存储库类。

我正在做你正在做的事情,并且出于同样的原因。您将看到LINQ生成的SQL可能是次优的,因此直接复制相同的次优SQL以供Dapper使用对我而言似乎是一种毫无意义的练习。

我所做的是确定执行最差的LINQ查询,并在SQL中重写它们 - 从头开始​​ - 与Dapper一起使用。我最终得到的是LINQ和Dapper在整个系统中的结合,受益于两种方法的优势,即LINQ的快速开发,以及Dapper和优化的SQL查询的性能提升。