Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当其中返回0行时,LINQ查询null异常_C#_.net_Linq_Linq To Sql_.net 3.5 - Fatal编程技术网

C# 当其中返回0行时,LINQ查询null异常

C# 当其中返回0行时,LINQ查询null异常,c#,.net,linq,linq-to-sql,.net-3.5,C#,.net,Linq,Linq To Sql,.net 3.5,我有下面的LINQ方法,它按预期工作,除非没有找到行,否则我会得到一个Null异常。如果出现这种情况,我正在努力修改它以返回0 public static int GetLastInvoiceNumber(int empNumber) { using (var context = new CmoDataContext(Settings.Default.LaCrosse_CMOConnectionString)) { cont

我有下面的LINQ方法,它按预期工作,除非没有找到行,否则我会得到一个Null异常。如果出现这种情况,我正在努力修改它以返回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)))
                            );
        }
    }
你正在使用

.Where(...)
.DefaultIfEmpty()
也就是说,如果没有结果,就假设它是一个带有单个空结果的序列。然后尝试在Max调用中使用该空结果

您可能可以将其更改为:

return tGreenSheet.Where(gs => ...)
                  .Max(gs => (int?) Convert.ToInt32(...)) ?? 0;
这使用重载查找
int?
值的最大值,并返回
int?如果没有值,则为null。
??0
然后将该空值转换为0。至少,这是LINQ对对象的行为。。。你必须检查它是否给你同样的结果

当然,您不需要使用
??0
如果您愿意将方法签名改为返回
int?
。这将提供额外的信息,因为调用方随后可以区分“无数据”和“最大值为0的某些数据”之间的差异:

另一个选项是使用
DefaultIfEmpty()
的重载,该重载接受一个值,如下所示:

return tGreenSheet.Where(gs => ...)
                  .Select(gs => Convert.ToInt32(...))
                  .DefaultIfEmpty(0)
                  .Max();

在这样的情况下,可能有匹配项,也可能没有匹配项,我更喜欢返回对象而不是值类型。如果您返回一个值类型,您必须对值的含义有一些语义,即“这里什么都没有”。我会将其更改为返回最后一张发票,然后(当它不为null时)从发票中获取发票号。向类添加一个方法以从字符串返回数字发票号

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

        return context.GetTable<tblGreenSheet>()
                      .Where(gs => gs.InvoiceNumber.Substring(2, 4) == empNumber.ToString())
                      .OrderByDescending(gs => Convert.ToInt32(gs.InvoiceNumber.Substring(6, gs.InvoiceNumber.Length)))
                      .FirstOrDefault();
    }
}

public class tbleGreenSheet
{
    ....
    public int NumericInvoice
    {
        get { return Convert.ToInt32(InvoiceNumber.Substring(6, InvoiceNumber.Length)); }
    }
    ...
}

我对
IQueryable
和NHibernate有着非常相似的经历。我的解决方案:

public static TExpr MaxOrDefault<TItem, TExpr>(this IQueryable<TItem> query,
                                               Expression<Func<TItem, TExpr>> expression) {
  return query.OrderByDescending(expression).Select(expression).FirstOrDefault();
}
public static TExpr MaxOrDefault(此IQueryable查询,
表达式(表达式){
返回query.OrderByDescending(表达式).Select(表达式).FirstOrDefault();
}

唯一的缺点是您一直使用标准默认值,而不是指定一个。

我建议您将LINQ查询拆分为单个方法调用,以找出问题所在。我想我更喜欢从方法返回一个
int?
,而不是使用一个神奇的值来表示不匹配。@tvanfosson:通常我也会这样做,但我试图匹配OP的要求。将进行编辑以表明这一点。我可以返回
int?
,但我无法以那种方式编译它。我得到了这个
错误8'System.Linq.IQueryable'不包含'Max'的定义和最佳扩展方法重载'System.Linq.Enumerable.Max(System.Collections.Generic.IEnumerable,System.Func)'有一些无效参数
@RefractedPaladin:Doh,类型参数的数目错误。将修复。@RefractedPaladin:Edited-查看是否有帮助。
public static tbleGreenSheet GetLastInvoice(int empNumber)
{
    using (var context = new CmoDataContext(Settings.Default.LaCrosse_CMOConnectionString))
    {
        context.Log = Console.Out;

        return context.GetTable<tblGreenSheet>()
                      .Where(gs => gs.InvoiceNumber.Substring(2, 4) == empNumber.ToString())
                      .OrderByDescending(gs => Convert.ToInt32(gs.InvoiceNumber.Substring(6, gs.InvoiceNumber.Length)))
                      .FirstOrDefault();
    }
}

public class tbleGreenSheet
{
    ....
    public int NumericInvoice
    {
        get { return Convert.ToInt32(InvoiceNumber.Substring(6, InvoiceNumber.Length)); }
    }
    ...
}
var invoice = Foo.GetLastInvoice( 32 );
if (invoice != null)
{
     var invoiceNumber = invoice.NumericInvoice;

     ...do something...
}
else
{
     ...do something else...
}
public static TExpr MaxOrDefault<TItem, TExpr>(this IQueryable<TItem> query,
                                               Expression<Func<TItem, TExpr>> expression) {
  return query.OrderByDescending(expression).Select(expression).FirstOrDefault();
}