web-dev-qa-db-ja.com

エンティティフレームワークを使用した動的クエリの作成

エンティティフレームワークとlinqを使用して動的クエリを作成する最良の方法は何かを知りたいです。

ソートおよびフィルタリング用の多くのパラメーター(50以上)を持つサービスを作成したい。これらが記入されるGUIからオブジェクトを取得します...そしてクエリは単一のサービスメソッドから実行されます。

周りを見回したところ、メソッドの最後に実行できる文字列を動的に作成できることがわかりました。私はこの方法があまり好きではありません。これを行うためのより良い方法はありますか?できればコンパイルチェックでタイプセーフですか?

39
Eduard

IQueryable<T>ステップバイステップ。ユーザーがどのようにフィルタリングしたいかを記述するFilterDefinitionクラスがあると仮定します...

public class FilterDefinition
{
    public bool FilterByName { get; set; }
    public string NameFrom { get; set; }
    public string NameTo { get; set; }

    public bool FilterByQuantity { get; set; }
    public double QuantityFrom { get; set; }
    public double QuantityTo { get; set; }
}

...その後、次のようなクエリを作成できます。

public IQueryable<SomeEntity> GetQuery(FilterDefinition filter)
{
    IQueryable<SomeEntity> query = context.Set<SomeEntity>();
    // assuming that you return all records when nothing is specified in the filter

    if (filter.FilterByName)
        query = query.Where(t => 
            t.Name >= filter.NameFrom && t.Name <= filter.NameTo);

    if (filter.FilterByQuantity)
        query = query.Where(t => 
            t.Quantity >= filter.QuantityFrom && t.Quantity <= filter.QuantityTo);

    return query;
}
54
Slauma

私が知っている他の唯一の方法は、フィルター値に基づいてIQueryableを構築することです。

    public List<Contact> Get(FilterValues filter)
    {
        using (var context = new AdventureWorksEntities())
        {
            IQueryable<Contact> query = context.Contacts.Where(c => c.ModifiedDate > DateTime.Now);

            if (!string.IsNullOrEmpty(filter.FirstName))
            {
                query = query.Where(c => c.FirstName == filter.FirstName);
            }

            if (!string.IsNullOrEmpty(filter.LastName))
            {
                query = query.Where(c => c.LastName == filter.LastName);
            }

            return query.ToList();
        }
    }
33
BrandonZeider

generic repository を作成しました。既知のフィールドと動的フィールドの両方でクエリとソートを行う統一APIをサポートしています。

       //Filter on known fields
       var keyboard = Query<Product>.Create(p=>p.Category=="Keyboard");
       var keyboards = repository.Get(keyboard);

       //Or filter on dynamic fields
       var filter = Query<Product>.Create("Rating", OperationType.GreaterThan, 4)
       var filteredKeyboards = repository.Get(filter);

       //You can also combine two queries togather
       var filterdKeyboards2 = repository.Get(keyboard.And(filter))

       //Order it on known fields
       var orderedKeyboard = keyboard.OrderBy(o=>o.Asc(p=>p.Name));
       var orderedKeyboards = repository.Get(orderedKeyboard);

       //Or order by on dynamic fields
       var userOrdering = keyboard.OrderBy(o=>o.Asc("Name"));
       var orderedKeyboards2 = repository.Get(userOrdering);

取得する検索オブジェクト/ DTOについては知りませんが、一般的な検索オブジェクト/ DTOを簡単に作成し、数行のコードでクエリオブジェクトにマップできます。私は過去にWCFサービスでそれを使用しましたが、私にとっては非常にうまく機能しました。

6
Gurmit Teotia

WCF Data Servicesを使用してサービスを作成し、動的にURIを作成してエンティティモデルを照会することができます。

1
Thomas Li