2011-02-01 186 views
1

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

如果问题是因为参数名称是一样的,在表中的列名,所以我改变了参数名称@StartDate@EndDate@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; 
    } 

回答

1

您已经完成它的方式,OleDb正在使用位置参数插入,因此您的SQL中的第一个参数'@EndDate'将被替换为传递的第一个参数'@StartDate'。使用位置插入时,参数的名称完全被忽略。

但是,这是一个鲜为人知的事实,即OleDb实际上是否接受命名参数。你只需要在SQL中声明参数。

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

如果你不声明SQL中的参数,OLEDB使用纯粹的定位参数插入,并在这些参数的名称相匹配的SQL不要紧,或者如果参数用于在SQL中两次 - 它只会从头到尾依次通过并盲目地替换SQL中找到的任何参数。

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

0

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

“SELECT t001_clients.cli_id as id,t001_clients.cli_name WHERE(id = 1);”

是不是最好的方式,但会工作。请注意参数的类型字符(“cli_name ='John Smith'”或“cli_birthday =#12/27/1980#”)

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

+0

这不会是一个可以接受的解决方案,我们希望使用命名参数进行一般的易用性。至于linq ...有没有linq访问?我认为有一个第三方的解决方案,如何做更新和插入到您的数据库,你可以通过LINQ做到这一点... – 2011-02-02 10:41:42