SQL到LINQ查询,其中where子句中的日期无效

本文关键字:子句 日期 无效 where 其中 LINQ 查询 SQL | 更新日期: 2023-09-27 18:14:10

我尝试通过LINQ查询数据库项,但它不起作用。例外只是:

对象引用未设置为对象的实例。

堆栈竞争和异常本身一样毫无帮助:

在SQLite。表查询1.CompileExpr(Expression expr, List 1queryArgs(,位于SQLite。表查询1.CompileExpr(Expression expr, List 1 queryArgs(d: ''XX''XX''XX''XX''SQLite.cs:line 2388SQLite。表查询1.CompileExpr(Expression expr, List 1 queryArgs(d: ''XX''XX''XX''XX''SQLite.cs:line 2308SQLite。表查询1.CompileExpr(Expression expr, List 1 queryArgs(d: ''XX''XX''XX''XX''SQLite.cs:line 2308SQLite。表查询1.CompileExpr(Expression expr, List 1 queryArgs(d: ''XX''XX''XX''XX''SQLite.cs:line 2308SQLite。中的TableQuery 1.GenerateCommand(String selectionList) in d:'XX'XX'XX'XX'XX'SQLite.cs:line 2274 at SQLite.TableQuery 1.GetEnumerator((d: ''XX''XX''XX''XX''SQLite.cs:line 2521系统集合。通用的列出1..ctor(IEnumerable 1集合(
在系统中。林克。可枚举。ToList[TSource](IEnumerable`1源(位于Kapital。数据模型。DataManagerOnetimeExpense<>c_DisplayClass5.b_4((在d:''XX''XX''XX''XX''DataModel''DataManagerOnetimeExpense.cs:line 47
在SQLite。SQLiteConnection。中的RunInTransaction(操作操作(d: ''XX''XX''XX''XX''SQLite.cs:line 906 atKapital。数据模型。DataManagerOnetimeExpense。RetrieveItems(Int32个月,Int32年,布尔值isPayed(d: ''XX''XX''XX ''XX''DataModel''DataManagerOnetimeExpense.cs:line 39 atUnitTestKapital。数据库TestDataManager一次性支出。TestRetrieveItemsByMonthYearIsPaid((在里面d: ''XX''XX''XX''XX''UnitTestKapital''Database''TestDataManagerOnetimeExpense.cs:line154

然而,以下是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#。净额4.5。这是一个WPF应用程序。

编辑:这是我的数据对象,它是一个简单的POCO。PaymentDate是用DateTime初始化的。今天,因此永远不会无效。

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

SQL到LINQ查询,其中where子句中的日期无效

这不是一个直接的解决方案,但您可以通过不同的过滤方式来规避这个问题。假设您要筛选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])。这样的表达式是不可搜索的,即数据库引擎不能使用索引进行查找。

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

这对我有用。