如何高效地将 EF linq 查询迁移到 Dapper?
How to efficiently migrate EF linq queries to Dapper?
我正在尝试将 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。
有没有人有比我现在想的更好的方法来做到这一点?
您可以使用Entity Framework Logging将生成的SQL输出到Visual Studio控制台。就像添加一样简单:
_context.Database.Log = x => Trace.WriteLine(x);
到您的服务或存储库 class(es)。
出于同样的原因,我正在做你正在做的事情。您会看到 LINQ 生成的 SQL 可能是次优的,因此直接复制相同的次优 SQL 供 Dapper 使用在我看来是毫无意义的练习。
我所做的是确定性能最差的 LINQ 查询,并在 SQL 中重写它们 - 从头开始 - 以便与 Dapper 一起使用。我最终得到的是整个系统中 LINQ 和 Dapper 的组合,受益于这两种方法的优势,即 LINQ 的快速开发,以及 Dapper 和优化 SQL 查询的性能提升。
我找到了解决我自己问题的良药。我没有拦截查询,而是允许传递谓词并创建与现有函数相同的 Linq 类函数。
public class QueryLinq
{
private readonly IDatabase _database;
public QueryLinq(IDatabase database)
{
_database = database; // Dapper implementation
}
public IEnumerable<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);
}
}
在这种方法中,我不需要担心现有查询。
2018 年 8 月 16 日更新:有关此方法的完整详细信息,请访问 here。
我正在尝试将 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。
有没有人有比我现在想的更好的方法来做到这一点?
您可以使用Entity Framework Logging将生成的SQL输出到Visual Studio控制台。就像添加一样简单:
_context.Database.Log = x => Trace.WriteLine(x);
到您的服务或存储库 class(es)。
出于同样的原因,我正在做你正在做的事情。您会看到 LINQ 生成的 SQL 可能是次优的,因此直接复制相同的次优 SQL 供 Dapper 使用在我看来是毫无意义的练习。
我所做的是确定性能最差的 LINQ 查询,并在 SQL 中重写它们 - 从头开始 - 以便与 Dapper 一起使用。我最终得到的是整个系统中 LINQ 和 Dapper 的组合,受益于这两种方法的优势,即 LINQ 的快速开发,以及 Dapper 和优化 SQL 查询的性能提升。
我找到了解决我自己问题的良药。我没有拦截查询,而是允许传递谓词并创建与现有函数相同的 Linq 类函数。
public class QueryLinq
{
private readonly IDatabase _database;
public QueryLinq(IDatabase database)
{
_database = database; // Dapper implementation
}
public IEnumerable<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);
}
}
在这种方法中,我不需要担心现有查询。
2018 年 8 月 16 日更新:有关此方法的完整详细信息,请访问 here。