1

私の WCF サービスのビジネス ロジックには、1 つ以上の列でユーザーをフィルター処理できる関数があります。フィルタリングを行う方法は次のとおりです。

public List<UserDto> GetUsersByFilters    (
                                              String ssn, 
                                              List<Guid> orderIds, 
                                              List<MaritalStatusEnum> maritalStatuses, 
                                              String name, 
                                              int age
                                          )
{
    using (MyProjEntities entities = new MyProjEntities())
    {
        IQueryable<User> users = entities.Users;

        // Filter By SSN (check if the user's ssn matches)
        if (String.IsNullOrEmusy(ssn) == false)
            users = users.Where(us => us.SSN == ssn);

        // Filter By Orders (check fi the user has all the orders in the list)
        if (orderIds != null)
            users = users.Where(us => UserContainsAllOrders(us, orderIds));

        // Filter By Marital Status (check if the user has a marital status that is in the filter list)
        if (maritalStatuses != null)
            users = users.Where(pt => maritalStatuses.Contains((MaritalStatusEnum)us.MaritalStatus));

        // Filter By Name (check if the user's name matches)
        if (String.IsNullOrEmusy(name) == false)
            users = users.Where(us => us.name == name);

        // Filter By Age (check if the user's age matches)
        if (age > 0)
            users = users.Where(us => us.Age == age);


        return users.ToList();
    }
}

private   Boolean   UserContainsAllOrders(User user, List<Guid> orderIds)
{
    return orderIds.All(orderId => user.Orders.Any(order => order.Id == orderId));
}

私の質問は次のとおり です。データベースで発生するクエリとローカルで発生するクエリは何ですか?

明らかに、データベース内のすべてのユーザーが毎回メモリにフェッチされることは望ましくありません...

「Filter By Orders」はローカル関数を使用しているため、データベースでは実行できないため、ローカルで実行されていると思います。私は正しいですか?

もしそうなら、結果として、その後に起こることはすべてローカルでも起こるということですか?

また、「注文によるフィルター」がなかったらどうなるでしょうか? データベース側ですべてが行われますか?

LINQ-TO-EF は、「婚姻状況」クエリをデータベース側のクエリに「変換」する方法を知っていますか? (関数に渡された列挙型のリストにユーザーの婚姻状況列挙型が存在するかどうかを確認しています)。

ありがとう !

[編集: 申し訳ありません。コードが自動色付けされない理由がわかりません]

4

1 に答える 1

1

さまざまな「where」ステートメントにカーソルを合わせると、それらが IQueryable のものであることがわかります (または、少なくともそうあるべきです)... Iqueryable の「where」を互いに追加し続ける限り、ステートメントはそのままですIqueryable (毎回データベースを呼び出さない)。

最終的に下部で ToList を実行すると、実際にデータベースが呼び出されます。

実際には、linq to ent ステートメントを作成する際に注意を払い、必要よりも早く IEnumerable を返す拡張機能を誤って呼び出さないようにすることが非常に重要です。誤って IEnumerable を返す拡張機能を呼び出してから、"skip" と "take" の呼び出しを開始し、SQL サイド ページングを実行しようとした場合、見逃していることになります...最適化された SQL クエリを作成するのではなく、オブジェクト。

正確に何が起こっているかについては、プロファイラーを開いて、ToList (またはその他の IEnumerable 拡張機能) を呼び出したときに送信される sql クエリを確認すると、最も興味深いものになります。Linq to Ent は通常、かなり最適化された SQL ステートメントを作成します。たとえば、Iqueryable Skip と Take を追加すると、Linq to Ent は、RowNumber に必要な SQL などを生成して、SQL サーバー側のページングを効率的に実行できるようにします。(クエリがより複雑になると、Linq to Ent は最も最適化されたクエリを作成するのが難しくなることに注意してください。複雑なクエリに時間がかかりすぎるようになった場合は、送信される SQL をトラップすることをお勧めします。より最適化された独自のクエリを作成できることが多いためです。そのような場合は問い合わせてください)。

この方法でもSQLをトレースできます

于 2012-06-08T15:52:31.693 に答える