1

IEnumerable<User>結果を返すためにLinq/Entity Framework /SQLServerを使用していたものを返すメソッドがあります。

難しい条件付きシナリオに遭遇しました。これは、WebサーバーでのC#反復ではるかに簡単に解決されました(linqステートメントのチェーンの最後で、データをクライアントに返す直前)。

public IEnumerable<User> ReturnUsersNotInRoles()
{
    IQueryable<User> z = (from users
                    //...many joins..conditions...
                    ).Distinct().Include(x => x.RoleUserLinks).ToList()


    IEnumerable<User> list = new List<User>();

    foreach (User user in z)
    {
        bool shouldReturnUser = true;

        foreach (var rul in user.RoleUserLinks)
        {
            if (rul.LinkStatusID == (byte)Enums.LinkStatus.Added)
                shouldReturnUser = false;
        }
        if (shouldReturnUser)
            list.Add(user);
    }

    return list;
}

質問:C#では、これを行うためのパフォーマンスが高く、メモリオーバーヘッドが少ない方法がありますか?

必要なエンティティをLinqから戻すだけです。N+1シナリオはありません。現在、パフォーマンスは優れています。

理想的には、これをSQL / Linqで記述していると思います。そうすると、SQL Serverがその魔法を実行し、データをすばやく提供してくれるからです。ただし、これと、理解するための潜在的にv.hardのクエリ、現在の反復による優れたパフォーマンス、およびC#の方法の理解のしやすさのバランスを取っています。

4

2 に答える 2

2

これはどう:

public IEnumerable<User> ReturnUsersNotInRoles()
{
    var z = (from users
                    //...many joins..conditions...
                    ).Distinct().Include(x => x.RoleUserLinks);

    var addedLinkStatusID = (int)Enums.LinkStatus.Added;
    return z.Where(user => 
               false == user.RoleUserLinks.Any(link => link.LinkStatusID == addedLinkStatusID))
            .ToList();
}

これは完全にSQLクエリとして実行する必要があります。最初の部分( )を定義する行の最後にをz追加することで、最初の部分()を実体化できます。.ToList()


ちなみに、「C#では、これを行うためのパフォーマンスが高く、メモリのオーバーヘッドが少ない方法はありますか?」という質問についてです。-まず、breakを設定した直後にステートメントを追加できますshouldReturnUser = false;

次に、データベースを使用しているかどうかに関係なく、可能な限りLINQプリミティブを使用することを好みます。

  1. 正しく使用すると、LINQメソッドを使用した実装は、おそらくあなたが書くことができるものと同じかそれよりも速くなります。
  2. さらに重要なことに、ステートフルでバグが発生しやすいプログラミングよりも、機能的でステートレスなプログラミングを促進します。
  3. また、データベースを使用している場合、コードをSQLクエリとして実行するかどうかを決定できるという利点があります。必要なのは、マテリアライズする場所を決定することだけです。
于 2013-01-09T20:36:26.197 に答える
0

あなたのループは次のLINQクエリと同等です-ループよりも理解しやすく、クエリの最初の部分と組み合わせるとサーバー上で完全に実行できます。

var linkStatusAdded = (Byte)Enums.LinkStatus.Added;

return z.Where(user => user.RoleUserLinks
                           .All(rul => rul.LinkStatusID != linkStatusAdded))
        .ToList();
于 2013-01-09T20:43:11.877 に答える