LINQ 経由でデータベース アイテムのクエリを実行しようとしましたが、うまくいきません。例外は次のとおりです。
オブジェクト参照がオブジェクト インスタンスに設定されていません。
スタック トレースは、例外自体と同じくらい役に立ちません。
SQLite.TableQuery
1.CompileExpr(Expression expr, List
1 queryArgs) で d:\XX\XX\XX\XX\XX\SQLite.cs:line 2383 で SQLite.TableQuery1.CompileExpr(Expression expr, List
1 queryArgs) で d:\XX\XX\XX\XX\XX\SQLite. cs:SQLite.TableQuery1.CompileExpr(Expression expr, List
1 queryArgs の 2388 行目 d:\XX\XX\XX\XX\XX\SQLite.cs:SQLite.TableQuery1.CompileExpr(Expression expr, List
1 queryArgs の 2308 行目 d:\XX\XX\XX\XX\ XX\SQLite.cs:1.CompileExpr(Expression expr, List
d:\XX\XX\XX\XX\XX\SQLite.cs:1.GenerateCommand(String selectionList) in d:\XX\XX\XX\XX\XX\SQLite.cs:line 2274 at SQLite.TableQuery
d:\XX\ の SQLite.TableQuery 1.GetEnumerator() の2308 行の SQLite.TableQuery 1 queryArgs) の 2308 行XX\XX\XX\XX\SQLite.cs: System.Collections.Generic.List1..ctor(IEnumerable
1 コレクションの 2521 行目)
System.Linq.Enumerable.ToList[TSource](IEnumerable`1 ソース) で 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(Int32 month, Int32 year, Boolean isPaid の 906 行目) ) 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 で初期化されるため、null になることはありません。
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;
}