1

我在 Access 数据库上执行以下查询。该查询在 Access 中运行时会返回准确的结果。但是,当从代码运行时,我会取回数据库中的所有项目,即使是那些超出我正在搜索的日期范围的项目。

我想知道问题是否是因为参数名称与表中的列名称相同,所以我更改了参数名称@StartDate@EndDateto@FromDate并且@ToDate这解决了问题,如果参数名称不同,我得到正确的结果集背部。这让我很担心,因为在我正在研究这种模式的项目中,到处都是重复的。但是,我使用一个名为的参数@Id来更新记录Id(db 表中的列名),这工作正常。这是一个奇怪的边缘案例吗?任何人都可以阐明这种行为。

为大量代码示例道歉,但在这种情况下,我认为需要整个方法。

  public override AcademicCycleTransportCollection FetchForDateRange(DateTime startDate, DateTime endDate) {
     const String query =
        "PARAMETERS \n" +
        "   @StartDate DATE, \n" +
        "   @EndDate DATE \n" +
        "   ; \n" +
        "SELECT \n" +
        "      [AcademicCycle].[Id] AS [Id], \n "  +
        "      [AcademicCycle].[Name] AS [Name], \n "  +
        "      [AcademicCycle].[AcademicCycleCategoryId] AS [AcademicCycleCategoryId], \n "  +
        "      [AcademicCycle].[ParentAcademicCycleId] AS [ParentAcademicCycleId], \n "  +
        "      [AcademicCycle].[StartDate] AS [StartDate], \n "  +
        "      [AcademicCycle].[EndDate] AS [EndDate], \n "  +
        "      [AcademicCycle].[IsPerpetual] AS [IsPerpetual], \n "  +
        "      [AcademicCycle].[IsLocked] AS [IsLocked] \n " +
        "FROM \n" +
        "  AcademicCycle \n" +
        "WHERE \n" +
        "  (StartDate <= @EndDate AND EndDate >= @StartDate) OR \n" +
        "  IsPerpetual <> 0";

     AcademicCycleTransportCollection transportCollection = new AcademicCycleTransportCollection();

     OleDbCommand _fetchForDateRangeCommand = null;

     if (_fetchForDateRangeCommand == null) {
        OleDbConnection connection = _parentDataConnection.Connection;
        _fetchForDateRangeCommand = new OleDbCommand(query, connection);
        _fetchForDateRangeCommand.Parameters.Add("@StartDate", OleDbType.Date);
        _fetchForDateRangeCommand.Parameters.Add("@EndDate", OleDbType.Date);
     }

     _fetchForDateRangeCommand.Transaction = _parentDataConnection.Transaction;

     _fetchForDateRangeCommand.Parameters["@StartDate"].Value = startDate;
     _fetchForDateRangeCommand.Parameters["@EndDate"].Value = endDate;

     using (OleDbDataReader dbReader = _fetchForDateRangeCommand.ExecuteReader()) {
        NullableDataReader reader = new NullableDataReader(dbReader);

        while (reader.Read()) {
           AcademicCycleTransport transport = FillTransport(reader);
           transportCollection.Add(transport);
        }
        if (!reader.IsClosed) {
           reader.Close();
        }
     }

     return transportCollection;
  }
4

2 回答 2

2

按照您的操作方式,OleDb 使用位置参数插入,因此您在 SQL 中的第一个参数“@EndDate”被传递的第一个参数“@StartDate”替换。使用位置插入时,参数的名称将被完全忽略。

然而,一个鲜为人知的事实是 OleDb 实际上确实接受命名参数。您还必须在 SQL 中声明参数。

请参阅:low-bandwidth.blogspot.com.au/2013/12/positional-msaccess-oledb-parameters.html

如果您不在 SQL 中声明参数,则 OleDb 使用纯位置参数插入,并且参数名称是否与 SQL 匹配,或者参数是否在 SQL 中使用两次都没关系 - 它只会通过和盲目地将 SQL 中找到的任何参数按从头到尾的顺序替换为传递的参数。

但是,如果您正确声明了参数,您将获得命名参数的好处,并且允许在 SQL 语句中多次重复参数。

于 2013-12-28T06:56:44.523 回答
0

尝试使用所需参数直接编辑查询字符串。简单示例(输出查询字符串):

“选择 t001_clients.cli_id 作为 id,t001_clients.cli_name WHERE (id = 1);”

不是最漂亮的方式,但会奏效。注意参数上的类型字符(“cli_name = 'John Smith'”或“cli_birthday = #12/27/1980#”)

另外,你为什么不使用 linq 查询?应该更容易...

于 2011-02-01T13:24:40.753 回答