【发布时间】:2013-05-13 18:05:45
【问题描述】:
我尝试通过 LINQ 查询数据库项目,但它不起作用。例外是:
对象引用未设置为对象的实例。
堆栈跟踪与异常本身一样无用:
在 SQLite.TableQuery
1.CompileExpr(Expression expr, List1 queryArgs) 在 d:\XX\XX\XX\XX\XX\SQLite.cs:line 2383 at SQLite.TableQuery1.CompileExpr(Expression expr, List1 queryArgs) 在 d:\XX\XX\XX\XX\XX\SQLite.cs:第 2388 行 SQLite.TableQuery1.CompileExpr(Expression expr, List1 queryArgs) 在 d:\XX\XX\XX\XX\XX\SQLite.cs:line 2308 at SQLite.TableQuery1.CompileExpr(Expression expr, List1 queryArgs) 在 d:\XX\XX\XX\XX\XX\SQLite.cs:line 2308 at SQLite.TableQuery1.CompileExpr(Expression expr, List1 queryArgs) 在 d:\XX\XX\XX\XX\XX\SQLite.cs:line 2308 at SQLite.TableQuery1.GenerateCommand(String selectionList) in d:\XX\XX\XX\XX\XX\SQLite.cs:line 2274 at SQLite.TableQuery1.GetEnumerator() 在 d:\XX\XX\XX\XX\XX\SQLite.cs:line 2521 at System.Collections.Generic.List1..ctor(IEnumerable1 个集合)
在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 源) 在 Kapital.DataModel.DataManagerOnetimeExpense.c__DisplayClass5.b__4() 在 d:\XX\XX\XX\XX\XX\DataModel\DataManagerOnetimeExpense.cs:47 行
在 SQLite.SQLiteConnection.RunInTransaction(Action action) 中 d:\XX\XX\XX\XX\XX\SQLite.cs:第 906 行 Kapital.DataModel.DataManagerOnetimeExpense.RetrieveItems(Int32 月, Int32 年,Boolean isPaid) in d:\XX\XX\XX\XX\XX\DataModel\DataManagerOnetimeExpense.cs:第 39 行 UnitTestKapital.Database.TestDataManagerOnetimeExpense.TestRetrieveItemsByMonthYearIsPaid() 在 d:\XX\XX\XX\XX\XX\UnitTestKapital\Database\TestDataManagerOnetimeExpense.cs:line 154
但是这里是 LINQ 查询:
public List<OnetimeExpense> RetrieveItems(int month, int year, bool isPaid)
{
var onetimeExpenses = new List<OnetimeExpense>();
connection.RunInTransaction(() =>
{
var items = from s in connection.Table<OnetimeExpense>()
let convertedDate = (DateTime)s.PaymentDate
where (convertedDate.Month == month)
&& (convertedDate.Year == year)
&& (s.IsPaid == isPaid)
select s;
onetimeExpenses = items.ToList();
});
return onetimeExpenses;
}
它肯定与日期有关,因为以下方法有效(基本上是相同的方法,没有日期的东西):
public List<OnetimeExpense> RetrieveItems(bool isPaid)
{
var onetimeExpenses = new List<OnetimeExpense>();
connection.RunInTransaction(() =>
{
var items = from s in connection.Table<OnetimeExpense>()
where (s.IsPaid == isPaid)
select s;
onetimeExpenses = items.ToList();
});
return onetimeExpenses;
}
有趣的部分来了:几个月前我收到了same issue 和一个 WinRT 应用程序。我设法以与上图相同的方式解决了这个问题。
我正在使用SQLite 3.7.16.2。 LINQ 提供程序是 sqlite-net。
还有什么? Visual Studio 2012、C#、.Net 4.5。它是一个 WPF 应用程序。
编辑: 这是我的数据对象,它是一个简单的 POCO。 PaymentDate 使用 DateTime.Today 进行初始化,因此永远不会为空。
public class OnetimeExpense : NotifyPropertyChanged
{
/**
* int Id
* string Name
* DateTime PaymentDate
* decimal Amount
* Boolean IsPaid
* */
#region getters and setters
private int id;
[PrimaryKey, AutoIncrement]
public int Id
{
get { return id; }
set
{
this.id = value;
this.OnPropertyChanged("Id");
}
}
private DateTime paymentDate = DateTime.Today;
public DateTime PaymentDate
{
get { return this.paymentDate; }
set
{
paymentDate = value;
this.OnPropertyChanged("PaymentDate");
}
}
private bool isPaid;
public bool IsPaid
{
get { return this.isPaid; }
set
{
this.isPaid = value;
this.OnPropertyChanged("IsPaid");
}
}
#endregion
#region Constructor
public OnetimeExpense(string name, decimal amount, DateTime paymentDate, bool isPaid)
{
this.name = name;
this.paymentDate = paymentDate;
this.amount = amount;
this.isPaid = isPaid;
}
public OnetimeExpense()
{
}
#endregion
}
编辑2 Gert Arnold 建议使用此解决方法。据我了解,它正在工作并且具有比我的查询更好的性能。不过,我想知道上面的查询有什么问题。
public List<OnetimeExpense> RetrieveItems(int month, int year, bool isPaid)
{
var onetimeExpenses = new List<OnetimeExpense>();
var lowerBound = new DateTime(year, month, 1);
var upperBound = lowerBound.AddMonths(1);
connection.RunInTransaction(() =>
{
var items = from s in connection.Table<OnetimeExpense>()
where s.PaymentDate >= lowerBound
&& s.PaymentDate < upperBound
&& s.IsPaid == isPaid
select s;
onetimeExpenses = items.ToList();
});
return onetimeExpenses;
}
【问题讨论】:
-
在这两个查询中,每个查询项中应该有多少个结果?
-
PaymentDate是可以为空的 DateTime 列吗?如果是这样,将空值转换为 DateTime 可能会出现问题? -
也许检查 s.PaymentDate 是否为空,类似于
where ((convertedDate != null ? convertedDate.Month : null) == month)... -
@MikePrecup:尝试使用空数据库和一些测试数据(大约 20 个条目)两次都出现相同的异常。
-
@TI 和 Netricity:我明天会重新检查,但我很确定 s.PaymentDate 不为空。看看我的数据模型,你可以看到 PaymentDate 是用 DateTime.Today 初始化的;其他参数(月、年和 isPaid)也不为空。
标签: c# linq sqlite linq-to-sql sqlite-net