我在Access数据库上执行以下查询。在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;
}
答案 0 :(得分: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语句中多次重复的命名参数和参数的好处。
答案 1 :(得分: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查询?应该更容易......