NullReferenceException 与 Nullable DateTime 尽管空检查

NullReferenceException with Nullable DateTime despite null check

GetTodayItemCount() 尝试使用 Items 模型中的 CreatedDtt 获取今天的项目计数。因为 CreatedDtt 是一个可空日期时间 (DateTime?),所以我在 Where 的 lambda 表达式中使用了一个三元运算符,以确保我以后不会尝试访问空值的日期在我的平等比较中。

但是,我仍然遇到经典的 NullReferenceException? Object reference not set to an instance of an object 错误,我可以确认 row.CreatedDtt.Value.Date 是问题所在。

  public Int64 GetTodayItemCount()
        {
            OrmLiteConnectionFactory dbFactory = new OrmLiteConnectionFactory(dbConn, SqlServerDialect.Provider);

            using (IDbConnection db = dbFactory.Open())
            {
                SqlExpression<Items> itemMatch = db.From<Items>()
                     .Where(row =>
                        (row.CreatedDtt.HasValue ?
                        row.CreatedDtt.Value.Date : DateTime.MinValue) == DateTime.Today
                      );

                Int64 itemCount = db.Count(itemMatch);
                db.Close();

                return itemCount;
            }
        }

当我事先检查其有效值时,如何访问 row.CreatedDtt.Value.Date,以及如何在不出现 NullReferenceException 错误的情况下实现 GetTodayItemCount() 的预期结果?

由于解决方案似乎不像我预测的那么简单,我在下面添加堆栈跟踪以防它有任何用处:

   at ServiceStack.OrmLite.SqlExpression`1.GetQuotedColumnName(ModelDefinition tableDef, String memberName)
   at ServiceStack.OrmLite.SqlExpression`1.GetMemberExpression(MemberExpression m)
   at ServiceStack.OrmLite.SqlExpression`1.VisitMemberAccess(MemberExpression m)
   at ServiceStack.OrmLite.SqlExpression`1.Visit(Expression exp)
   at ServiceStack.OrmLite.SqlExpression`1.VisitBinary(BinaryExpression b)
   at ServiceStack.OrmLite.SqlExpression`1.Visit(Expression exp)
   at ServiceStack.OrmLite.SqlExpression`1.VisitBinary(BinaryExpression b)
   at ServiceStack.OrmLite.SqlExpression`1.Visit(Expression exp)
   at ServiceStack.OrmLite.SqlExpression`1.VisitLambda(LambdaExpression lambda)
   at ServiceStack.OrmLite.SqlExpression`1.Visit(Expression exp)
   at ServiceStack.OrmLite.SqlExpression`1.AppendToWhere(String condition, Expression predicate)
   at ServiceStack.OrmLite.SqlExpression`1.Where(Expression`1 predicate)
   at GroupRedemptionsScanner.DBHandlers.GetTodayItemCount() in [directory/file/line number etc]

您不能将 C# 逻辑应用于 RDBMS 服务器列。如果你想测试像日期这样的模糊精度数据类型,你应该使用一个范围,例如:

.Where(row => row.CreatedDtt != null && 
              row.CreatedDtt >= DateTime.Now.Date && 
              row.CreatedDtt <  DateTime.Now.Date.AddDays(1)));

我试图以您能想到的所有方式重现您的错误,但我做不到。唯一的方法是明确地将一行保留为空。但我不知道这是否可能。无论如何,我建议您使用 Null Propagation 重构它。这样:

.Where(row => row?.CreatedDtt?.Date == DateTime.Today);