我尝试通过 LINQ 查询数据库项目,但它不工作。唯一的例外是:
你调用的对象是空的。
堆栈跟踪与异常本身一样无用:
在 SQLite.TableQuery
1.CompileExpr(Expression expr, List
1 queryArgs) 在 d:\XX\XX\XX\XX\XX\SQLite.cs:line 2383 at SQLite.TableQuery1.CompileExpr(Expression expr, List
1 queryArgs) 在 d:\XX\XX\XX\XX\XX\SQLite. cs:1.CompileExpr(Expression expr, List
d:\XX\XX\XX\XX\XX\SQLite.cs 中 SQLite.TableQuery 1 queryArgs 的第 2388 行:d:\XX\XX\XX\XX\ 中 SQLite.TableQuery 1 queryArgs 的第 23081.CompileExpr(Expression expr, List
行XX\SQLite.cs: d:\XX\XX\XX\XX\XX\SQLite.cs: SQLite.TableQuery 1.GetEnumerator() in d:\XX1.CompileExpr(Expression expr, List
\XX\XX\XX\XX\SQLite.cs:line 2308 at SQLite.TableQuery 1 queryArgs)1.GenerateCommand(String selectionList) in d:\XX\XX\XX\XX\XX\SQLite.cs:line 2274 at SQLite.TableQuery
XX\XX\XX\XX\SQLite.cs:System.Collections.Generic.List1..ctor(IEnumerable
1 集合的第 2521 行)
在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) 在 Kapital.DataModel.DataManagerOnetimeExpense.<>c__DisplayClass5.b__4() 在 d:\XX\XX\XX\XX\XX\DataModel\DataManagerOnetimeExpense.cs :
d:\XX\XX\XX\XX\XX\SQLite.cs 中 SQLite.SQLiteConnection.RunInTransaction(Action action) 的第 47 行:Kapital.DataModel.DataManagerOnetimeExpense.RetrieveItems 的第 906 行(Int32 月,Int32 年,Boolean isPaid ) 在 d:\XX\XX\XX\XX\XX\DataModel\DataManagerOnetimeExpense.cs:第 39 行 UnitTestKapital.Database.TestDataManagerOnetimeExpense.TestRetrieveItemsByMonthYearIsPaid() 在 d:\XX\XX\XX\XX\XX\UnitTestKapital\Database \TestDataManagerOnetimeExpense.cs:第 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;
}
有趣的部分来了:几个月前我在 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
}
Edit2 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;
}