1

Access データベースで実行している次のクエリがあります。クエリを Access で実行すると、正確な結果が返されます。ただし、コードから実行すると、データベース内のすべてのアイテムが返されます。検索している日付範囲外のものも含まれます。

パラメータ名がテーブルの列名と同じであるため、問題が発生したのではないかと思っていたので、パラメータ名を変更して@StartDate@EndDateこれ@FromDate@ToDate問題が修正されました。パラメータ名が異なる場合、正しい結果セットが得られます戻る。私が取り組んでいるプロジェクトでは、このパターンがいたるところに複製されているため、これは私にとって懸念事項です。ただし、 (db テーブルの列名) で@Idレコードを更新するという名前のパラメーターを使用していますが、これは正常に機能しています。Idこれは奇妙なエッジケースですか?誰でもこの動作に光を当てることができますか?

大量のコード サンプルで申し訳ありませんが、この場合はメソッド全体が必要だと思います。

  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 で 2 回使用されているかどうかは関係ありません。 SQL で見つかったパラメーターを最初から最後まで順番に、渡されたものに盲目的に置き換えます。

ただし、パラメーターを正しく宣言すると、名前付きパラメーターとパラメーターを SQL ステートメント内で複数回繰り返すことができるという利点が得られます。

于 2013-12-28T06:56:44.523 に答える
0

必要なパラメータを使用してクエリ文字列を直接編集してみてください。簡単な例(出力クエリ文字列):

"SELECT t001_clients.cli_id as id、t001_clients.cli_name WHERE(id = 1);"

最もきれいな方法ではありませんが、機能します。パラメータのタイプ文字に注意してください( "cli_name='JohnSmith'"または"cli_birthday=#12/27/1980#")

また、なぜlinqクエリを使用しなかったのですか?簡単なはずです...

于 2011-02-01T13:24:40.753 に答える