如何让LINQ Lambda表达式像XPath一样优雅地失败?

时间:2013-06-24 22:02:08

标签: linq linq-to-sql linq-to-entities

更一般的问题,但是如何编写LINQ Lambda表达式,以便在LINQ表达式失败或不返回任何内容时,它们将返回默认字符串或仅返回空字符串。在XSLT XPath中,如果匹配失败,那么一个什么都没有,并且应用程序没有崩溃,而在LINQ中似乎有例外。

我使用First()并尝试过FirstOrDefault()。

所以示例查询可能是:

Customers.First(c=>c.id==CustId).Tasks.ToList();

Customers.Where(c=>c.id==CustId).ToList();

Model.myCustomers.Where(c=>c.id==CustId);

无论查询是什么,如果它没有返回任何记录或null,那么是否有一种通用的方法来确保查询正常失败?

感谢。

3 个答案:

答案 0 :(得分:1)

如果没有匹配的记录,

Customers.First(c=>c.id==CustId)将崩溃。

有几种方法可以尝试找到它,如果您使用FirstOrDefault,如果找不到匹配项则会返回NULL并且您可以检查NULL

或者,您可以使用.Any语法检查您是否有任何记录并返回boolean

答案 1 :(得分:1)

当您访问属性时,C#中没有任何内容可以传播空值。您可以创建自己的扩展方法:

public static class Extensions
{
    public static TValue SafeGet<TObject, TValue>(
        this TObject obj, 
        Func<TObject, TValue> propertyAccessor)
    {
        return obj == null ? default(TValue) : propertyAccessor(obj);
    }

    public static IEnumerable<T> OrEmpty<T>(this IEnumerable<T> collection)
    {
        return collection ?? Enumerable.Empty<T>();
    }
}

像这样使用:

Customers.FirstOrDefault(c => c.id==CustId).SafeGet(c => c.Tasks).OrEmpty().ToList();

答案 2 :(得分:0)

我期望抛出异常的唯一查询是第一个(假设Customers是有效集合而不是null本身):

Customers.First(c=>c.id==CustId).Tasks.ToList();

如果没有id CustId FirstOrDefault的客户(您的财产和变量名称存在套管问题),则会抛出异常。

如果您不希望在不匹配时抛出异常,请在提及时使用var customer = Customers.FirstOrDefault(c => c.id == CustId); if (customer == null) { // deal with no match return; } var taskList = customer.Tasks.ToList(); ,并进行空检查,例如:

{{1}}