データアクセスのパフォーマンスを向上させるために、Entity Frameworkから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();
}
私がやりたいこと:
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の著者の1人は、誰かが尋ねると
Dapper.netをIQueryableインターフェイスに対応させる計画はありますか?
それ
これを行う計画はありません。それは、dapperがやろうとしていることからはかけ離れています。これまでのところ、私はそれがアンチテーゼであると言うでしょう。 Dapperコアは、SQLを愛する人々の友達になろうとします。
( https://stackoverflow.com/a/27588877/3813189 を参照)。
ある意味では、これは、あなたが提案したように、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; }
}
}
}
Dapper.Extensions.Linq (あなたが提案したパッケージ)も試しました。
これに基づいて構築され、Linqクエリを介した高度なDBアクセスを提供します。流動的な構成により、セットアップが簡単かつ迅速になります。
残念なことに、私もそれをうまく活用できませんでした。多くのドキュメントはなく、テストは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; }
}
}
}
..しかし、実行時にエラーで失敗しました
StackOverflowAnswer.Program + Productsの演算子が見つかりませんでした
Predicateを手動で生成する理由(最初の例)はわかりませんが、QueryBuilderはうまくいきません。
質問に残されたコメントが正しいように見えるようになっていると思います。EntityFrameworkで使用した式からコードを修正する必要があります。このQueryBuilderクラスに関する情報を見つけるのは非常に困難だったので、私は(たとえそれを機能させたとしても)遭遇した問題が助けを得るのが難しいことを心配します(そしてバグは修正されないかもしれません)。
属性を使用してEFとDapperを連携させるユーティリティを作成しました。述語を解析し、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);
}
}
}
そして簡単なクエリ:
using (var cn = new SqlConnection("..."))
{
var usersRepository = new DapperRepository<User>(cn)
var allUsers = await userRepository.FindAllAsync(x => x.AccountId == 3 && x.Status != UserStatus.Deleted);
}
たぶんそれはあなたに役立つでしょうか?