Как только у меня появятся результаты моего запроса Linq, я не всегда счастлив. Может быть, результат, который я ожидал быть там, но не был. Например, мой клиент ожидал, что клиент был в списке клиентов, но это не так. Это мой клиент, говорящий "Чувак, где мой клиент?", А не я. Я - Чувак, и, чтобы остаться чуваком, я должен отдать моему клиенту причину.
Есть ли простой способ взять экземпляр данного объекта и запрос Linq и определить, какие выражения в запросе исключили этот экземпляр?
Изменить Хорошо, вот лучший пример
Выход должен быть чем-то рядом:
Ваш Клиент был исключен по двум причинам:
Клиент 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
}
Прежде всего, прежде чем я попытаюсь написать какую-нибудь фэнтезийную флюидную фреймворк, Кто-нибудь уже сделал это?
До сих пор я рассматривал возможность навигации по дереву выражений и выполнению каждой ветки по отношению к IQueryable, которая содержит только мой объект. Теперь у меня нет большого опыта, использующего необработанные деревья выражений, поэтому мне бы хотелось, чтобы те, кто должен был предложить любые подводные камни, или даже объясняли, является ли это тупиком и почему.
Я беспокоюсь, что все, что вытекает из этого, должно:
- Быть многоразовым - должно быть применимо к любому объекту, сравниваемому с запросом Linq, возвращающим объекты того же класса.
- Не влияет на производительность исходного запроса (это должен быть только стандартный Linq).
- Должен быть агностик Linq-реализации.
- Если в отсутствующем экземпляре есть несколько значений свойств, исключающих его из результатов, то следует сообщить обо всех этих причинах.
Edit Я не предлагаю, чтобы я продолжал выполнять LinqToSql против базы данных несколько раз с различными перестановками запроса и сравнения результатов. Скорее, я ищу способ взять один экземпляр и сравнить его с деревом выражений (без выполнения запроса напрямую)
Кроме того, я хотел бы указать, могут ли другие найти это полезным. Если это так, я бы рассмотрел возможность запуска проекта с открытым исходным кодом для его решения.