2011-02-01 2 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 ... –

Смежные вопросы