当Where返回0行时,LINQ查询null异常

Ref*_*din 4 .net c# linq .net-3.5 linq-to-sql

我有以下LINQ方法,按预期工作,除非有没有找到行,然后我得到一个空例外.我正在努力如何修改它以返回0如果发生这种情况.

    public static int GetLastInvoiceNumber(int empNumber)
    {
        using (var context = new CmoDataContext(Settings.Default.LaCrosse_CMOConnectionString))
        {
            context.Log = Console.Out;

            IQueryable<tblGreenSheet> tGreenSheet = context.GetTable<tblGreenSheet>();

            return (tGreenSheet
                            .Where(gs => gs.InvoiceNumber.Substring(2, 4) == empNumber.ToString())
                            .DefaultIfEmpty()
                            .Max(gs => Convert.ToInt32(gs.InvoiceNumber.Substring(6, gs.InvoiceNumber.Length)))
                            );
        }
    }
Run Code Online (Sandbox Code Playgroud)

谢谢


我尝试了Jon Skeet的一个建议,现在我得到了 Unsupported overload used for query operator 'DefaultIfEmpty'

    public static int GetLastInvoiceNumber(int empNumber)
    {
        using (var context = new CmoDataContext(Settings.Default.LaCrosse_CMOConnectionString))
        {
            context.Log = Console.Out;

            IQueryable<tblGreenSheet> tGreenSheet = context.GetTable<tblGreenSheet>();

            return tGreenSheet
                            .Where(gs => gs.InvoiceNumber.Substring(2, 4) == empNumber.ToString())
                            .Select(gs => Convert.ToInt32(gs.InvoiceNumber.Substring(6, gs.InvoiceNumber.Length)))
                            .DefaultIfEmpty(0)
                            .Max();                                
        }
    }
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 11

你正在使用

.Where(...)
.DefaultIfEmpty()
Run Code Online (Sandbox Code Playgroud)

这意味着如果没有结果,假装它是一个具有单个null结果的序列.然后,您尝试在Max调用中使用该null结果...

您可以将其更改为:

return tGreenSheet.Where(gs => ...)
                  .Max(gs => (int?) Convert.ToInt32(...)) ?? 0;
Run Code Online (Sandbox Code Playgroud)

这使用重载找到int?值的最大值- int? null如果没有值,则返回a .在?? 0随后转换是空值0.至少,这就是LINQ到对象的行为......你必须检查它是否给你同样的结果.

当然,?? 0如果您愿意更改方法签名int?而不是返回,则不需要使用.这将提供额外的信息,因为调用者可以告诉"无数据"和"最大值为0的某些数据"之间的区别:

return tGreenSheet.Where(gs => ...)
                  .Max(gs => (int?) Convert.ToInt32(...));
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用其重载DefaultIfEmpty()值 - 如下所示:

return tGreenSheet.Where(gs => ...)
                  .Select(gs => Convert.ToInt32(...))
                  .DefaultIfEmpty(0)
                  .Max();
Run Code Online (Sandbox Code Playgroud)

  • +1我甚至没看过它,但是嘿,它必须*是正确的:-) (3认同)