Linqクエリの結果を取得した後は、常に満足しているとは限りません。私がそこにいることを期待していたが、そうではなかったという結果があるかもしれません。たとえば、私のクライアントは、顧客が顧客リストに含まれていることを期待していましたが、そうではありませんでした。私ではなく、「おい、私の顧客はどこ?」と言っているのは私のクライアントです。私は男です、そして男であり続けるために、私は私のクライアントに理由を与えなければなりません。
特定のオブジェクトインスタンスとLinqクエリを取得し、クエリ内のどの式がそのインスタンスを除外したかを判断する簡単な方法はありますか?
編集OK、これがより良い例です
出力は次のようになります。
あなたの顧客は2つの理由で除外されました:
顧客のFirstNameはCarlですが、Danielである必要があります
顧客の年齢は18歳ですが、20歳を超える必要があります
public class Customer
{
public string FirstName { get; set; }
public int Age { get; set; }
}
[Test]
public void Dude_wheres_my_object_test1()
{
var daniel = new Customer { FirstName = "Daniel", Age = 41 };
var carl = new Customer { FirstName = "Carl", Age= 18 };
var Customers = new List<Customer>() { daniel, carl };
// AsQueryable() to convert IEnumerable<T> to IQueryable<T> in
//the case of LinqtoObjects - only needed for this test, not
//production code where queies written for LinqToSql etc normally
//return IQueryable<T>
var query = from c in Customers.AsQueryable()
where c.Age > 20
where c.FirstName == "Daniel"
select c;
//query would return Daniel as you'd expect, but not executed here.
//However I want to explain why Carl was not in the results
string[] r = DudeWheresMyObject(query, carl);
Assert.AreEqual("Age is 18 but it should be > 20", r[0]);
Assert.AreEqual("FirstName is Carl but it should be Daniel", r[1]);
//Should even work for a Customer who is not
//in the original Customers collection...
var ficticiousCustomer = new Customer { FirstName = "Other", Age = 19};
string[] r2= DudeWheresMyObject(query,
ficticiousCustomer);
Assert.AreEqual("Age is 19 but it should be > 20", r2[0]);
Assert.AreEqual("FirstName is Other but it should be Daniel", r2[1]);
}
public string[] DudeWheresMyObject<T>(IQueryable<T> query, T instance)
{
//Do something here with the query.Expression and the instance
}
まず第一に、私がいくつかの派手なFluentフレームワークを書き込もうとする前に、誰かがこれをすでに行ったことがありますか?
これまで、式ツリーをナビゲートし、オブジェクトのみを含むIQueryableに対して各ブランチを実行することを検討してきました。今は生の表現ツリーを使った経験があまりないので、落とし穴を提案したり、行き止まりなのか、その理由を説明したりしてほしいと思います。
私はこれから生じるものはすべて次のようになるのではないかと心配しています。
- 再利用可能-同じクラスのオブジェクトを返すLinqクエリと比較して、すべてのオブジェクトに適用できる必要があります。
- 元のクエリのパフォーマンスには影響しません(これは標準のLinqである必要があります)。
- Linq実装に依存しない必要があります。
- 欠落しているインスタンスに複数のプロパティ値が設定されていて、結果から除外されている場合は、それらすべての理由を報告する必要があります。
編集 私は、クエリのさまざまな順列を使用してデータベースに対してLinqToSqlを複数回実行し続け、結果を比較することを提案していません。むしろ、単一のインスタンスを取得して、それを式ツリーと比較する方法を探しています(クエリを直接再度実行する必要はありません)。
また、他の人がこれが役立つかどうかを示したいと思います。もしそうなら、私はそれを解決するためにオープンソースプロジェクトを開始することを検討します。