1

IQueryableまたはIEnumerableデータ型は最初から結果を返さず、必要な場合にのみ結果を返すことを学びました。ただし、ウォッチインスペクターでそのオブジェクトを開くと、すべてのオブジェクトがそこにあることがわかりました。

私のコードに何か問題がありますか、それとも時計で呼び出したために表示されていますか?

[ウォッチダイアログボックスで保留中のオブジェクトを表示すると、すべてのリストアイテムが表示されましたが、最初からロードされないはずです。近づいてくるのに何か問題がありますか、それとも時計で呼んでいたので表示されているだけですか。]

 public IQueryable<PurchasePendingView> PurchasePendings() {
            var pendings = db.PurchasePendingViews
                             .Where(m => m.AccountStatusID != StructAccountStatus.Succeed); // when I view it in the watch dialougebox I saw all the list items but it shouldn't load at the first place. Is there anything wrong in my approaching or is it just showing because I had call it on the watch. 
            if (ApplicationEnvironment.DEBUGGING) {
                return pendings;
            } else if (IsMobileAccount()) {
                var showroom = db.ShowRooms.FirstOrDefault(m=> m.MemberID == employee.MemberID);
                if (showroom != null) {
                    return pendings.Where(m => m.ShowRoomID == showroom.ShowRoomID);
                } else {
                    return pendings.Where(m => m.CountryDivisionID == employee.CountryDivisionID);
                }
            } else { 
                //normal salary employee can see every detail
                return pendings;
            }
        }

注:現在、遅延読み込みはオフになっています。

4

2 に答える 2

6

コレクションは、結果を最初に繰り返すときに評価されます。

時計検査官で結果を繰り返し処理しているので、結果は評価されます。

于 2012-10-09T14:26:54.990 に答える
0

これは、説明するよりも説明する方が簡単です。

public class MeanException : Exception
{
    public MeanException() : base() { }
    public MeanException(string message) : base(message) { }
}
public static IEnumerable<T> Break<T>(this IEnumerable<T> source)
    where T : new()
{
    if (source != null)
    {
        throw new MeanException("Sequence was evaluated");
    }
    if (source == null)
    {
        throw new MeanException("Sequence was evaluated");
    }

    //unreachable

    //this will make this an iterator block so that it will have differed execution,
    //just like most other LINQ extension methods
    yield return new T();
}

public static IEnumerable<int> getQuery()
{
    var list = new List<int> { 1, 2, 3, 4, 5 };

    var query = list.Select(n => n + 1)
        .Break()
        .Where(n => n % 2 == 0);

    return query;
}

それで、ここには何がありますか。カスタム例外があるため、個別にキャッチできます。IEnumerable<T>シーケンスが評価されるとすぐに例外をスローする拡張メソッドがありますが、 Selectandと同様に、遅延実行を使用しWhereます。最後に、クエリを取得するメソッドがあります。Break呼び出しの前後の両方でLINQメソッドを確認できList、基になるデータソースとしてaが使用されていることがわかります。(あなたの例では、それはメモリ内のコレクションか、データベースにクエリを実行し、反復時に結果を反復処理するオブジェクトのいずれかである可能性があります。)

次に、このクエリを使用して、何が起こるかを見てみましょう。

try
{
    Console.WriteLine("Before fetching query");
    IEnumerable<int> query = getQuery();
    Console.WriteLine("After fetching query");
    foreach (var number in query)
    {
        Console.WriteLine("Inside foreach loop");
    }
    Console.WriteLine("After foreach loop");
}
catch (MeanException ex)
{
    Console.WriteLine("Exception thrown: \n{0}", ex.ToString());
}

このコードを実行すると、クエリ前の印刷(明らかに)クエリ後の印刷(メソッドからクエリを返したばかりで、平均例外がスローされなかったことを意味します)と、例外が発生したというメッセージが表示されます。スローされます(つまり、foreachループの内部または終了を超えたことはありません。

これは明らかに概念を示すために少し工夫された例ですが、これは実際に実際に十分頻繁に見られるものです。たとえば、データコンテキストの作成後にデータベースとの接続が失われた場合、クエリを繰り返すまで実際に例外が発生することはありません。または、データホルダーオブジェクトが古く、DBと一致しなくなった場合も同様です。同じ時点で例外が発生します。あまり明白ではない例では、クエリを長期間保持すると、クエリの結果を取得するときではなく、クエリの結果を取得するときにデータが表示されます。これはその別のデモンストレーションです:

var list = new List<int> { 1, 2, 3, 4, 5 };

var query = list.Where(num => num < 5);
Console.WriteLine(query.Count());

list.RemoveAll(num => num < 4);
Console.WriteLine(query.Count()

ここにデータのリストがあり、5未満(4)のアイテムの数を数えます。次に、リストを変更します(queryまったく変更しません)。再クエリqueryを実行すると、カウントは1になります。

于 2012-10-09T15:04:58.233 に答える