我尝试通过LINQ查询数据库项,但它无法正常工作。唯一的例外是:
对象引用未设置为对象的实例。
stacktrace与异常本身一样无益:
在SQLite.TableQuery
1.CompileExpr(Expression expr, List
1 queryArgs)在d:\ XX \ XX \ XX \ XX \ XX \ SQLite.cs:第2383行 SQLite.TableQuery1.CompileExpr(Expression expr, List
1 queryArgs)in d:\ XX \ XX \ XX \ XX \ XX \ SQLite.cs:第2388行 SQLite.TableQuery1.CompileExpr(Expression expr, List
1 queryArgs)in d:\ XX \ XX \ XX \ XX \ XX \ SQLite.cs:第2308行 SQLite.TableQuery1.CompileExpr(Expression expr, List
1 queryArgs)in d:\ XX \ XX \ XX \ XX \ XX \ SQLite.cs:第2308行 SQLite.TableQuery1.CompileExpr(Expression expr, List
1 queryArgs)in d:\ XX \ XX \ XX \ XX \ XX \ SQLite.cs:第2308行 SQLite.TableQuery1.GenerateCommand(String selectionList) in d:\XX\XX\XX\XX\XX\SQLite.cs:line 2274 at SQLite.TableQuery
1.GetEnumerator()in d:\ XX \ XX \ XX \ XX \ XX \ SQLite.cs:第2521行 System.Collections.Generic.List1..ctor(IEnumerable
1集合)
在System.Linq.Enumerable.ToList [TSource](IEnumerable`1 source)at 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 month, Int32年,Boolean isPaid)in d:\ XX \ XX \ XX \ XX \ XX \ DataModel \ DataManagerOnetimeExpense.cs:第39行at UnitTestKapital.Database.TestDataManagerOnetimeExpense.TestRetrieveItemsByMonthYearIsPaid() 在 d:\ XX \ XX \ XX \ XX \ XX \ UnitTestKapital \数据库\ 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应用程序获得了same issue。我设法以与上面所示相同的方式解决了这个问题。
我正在使用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;
}
答案 0 :(得分:2)
不是直接的解决方案,但您可以通过不同的过滤来规避问题。假设您要过滤2013年5月的记录:
var lowerBound = new DateTime(2013,5,1);
var upperBound = new DateTime(2013,6,1);
var items = from s in connection.Table<OnetimeExpense>()
where s.PaymentDate >= lowerBound
&& s.PaymentDate < upperBound
&& s.IsPaid == isPaid
select s;
这不仅仅是回避问题。当PaymentDate
上有索引时,它还有可能提高查询效率。像convertedDate.Year
这样的表达式被翻译为DATEPART(Year, [t0].[PaymentDate])
。这样的表达式不是sargable,即数据库引擎不能使用索引进行查找。
答案 1 :(得分:0)
if (LoggingFilter.StartDate.HasValue)
{
logs = auditlogs.Where(x => x.DateTime > auditLoggingFilter.StartDate).ToList();
}
if (LoggingFilter.EndDate.HasValue)
{
LoggingFilter.EndDate = LoggingFilter.EndDate.Value.AddTicks(DateTime.Now.TimeOfDay.Ticks);
logs = auditlogs.Where(x => x.DateTime < LoggingFilter.EndDate).ToList();
}
这对我有用。