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);
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);