【问题标题】:C# DataTable Date format in query查询中的 C# DataTable 日期格式
【发布时间】:2016-05-05 04:13:54
【问题描述】:

首先,我想指出,我知道要避免在 SQL 查询中直接使用 TextBox 或 DatePicker 中的字符串,如下面的代码所示。在我弄清楚如何完成这项工作后,我打算修复所有这些问题,但为了在最初编码和测试时简单起见,我现在正在使用它。我指出这一点是因为我在 Google 上找到的所有内容都指出了这一点,但似乎并没有给出真正问题的实际答案。 :) 话虽这么说,这里是...

我有一个 Access 2010 数据库 (.accdb),我需要从中读取数据以填充 WPF 中的多个文本框。无论我如何格式化查询中的日期,我都会得到一种或另一种异常。我一直在使用的代码是:

    public void UpdateEarlyStageData(string filePath, string query)
    {
        List<string> departments = new List<string>();

        string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;" +
            @"Data Source=" + filePath + ";" +
            @"User Id=;Password=;";

        using (OleDbConnection connection = new OleDbConnection(connectionString))
        {
            try
            {
                connection.Open();

                using (OleDbDataAdapter adapter = new OleDbDataAdapter(query, connection))
                {
                    System.Data.DataTable table = new System.Data.DataTable();
                    adapter.Fill(table);

                    massCellRecords.Text = table.Rows[0]["MASSCellRecords"].ToString();
                    massCellDials.Text = table.Rows[0]["MASSCellDials"].ToString();
                    massCellSaturation.Text = table.Rows[0]["MASSCellSaturation"].ToString();
                    massCellPercentTotal.Text = table.Rows[0]["MASSCellPercentVolume"].ToString();
                    massCellPercentWorked.Text = table.Rows[0]["MASSCellPassPenetration"].ToString();
                    massCellPassPercent.Text = table.Rows[0]["MASSCellTotalPassPenFactor"].ToString();

                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

    }

    private void recordDateES_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
    {            
        string filePath = "C:\\Dialer Team Back-End Database\\DialerTeam_be.accdb";
        DateTime targetDate = DateTime.Parse(recordDateES.ToString());
        //string queryString = "SELECT * FROM ESDialsPerList WHERE CallDate = #" + DateTime.Today.ToShortDateString() + "#";
        string queryString = "SELECT * FROM ESDialsPerList WHERE CallDate = #" + targetDate.ToShortDateString() + "#";
        //queryString = "SELECT * FROM ESDialsPerList WHERE CallDate = #" + targetDate + "#";
        queryString = "SELECT * FROM ESDialsPerList WHERE CallDate = #05//02//2016#";

        UpdateEarlyStageData(filePath, queryString);
    }

我见过的例外是:

InvalidOperationException:提供者无法确定 Double 值。

当我将查询格式化为queryString = "SELECT * FROM ESDialsPerList WHERE CallDate = #05/02/2016#"; 时会发生这种情况。我假设这里发生的事情是它试图将 05 除以 02,结果到 2016 年。

OleDbException:查询表达式“CallDate = #05//02//2016”中的日期语法错误

当我将查询格式化为queryString = "SELECT * FROM ESDialsPerList WHERE CallDate = #05//02//2016#"; 时会发生这种情况。我不知道为什么会这样,因为我还有其他使用这种格式的查询,唯一的区别是它们没有使用 DataTable,而只是直接使用OleDbDataReader

上面代码中被注释掉的每一行都反映了使这项工作发挥作用的各种尝试,但都没有奏效……请帮忙!

更新: 我还没有找到确切的解决方案或答案,但我确实有完成同样事情的工作代码。我没有使用 DataTable,而是直接使用 OleDbConnection。由于这并不是对所提问题的真正解决方案,因此我认为这本身并不是一个真正的答案,因此我将粘贴下面的代码,以便将来遇到类似问题的任何人都可以参考.

    private void saveData_Click(object sender, RoutedEventArgs e)
    {
        if (departmentSelector.SelectedIndex == 2)
        {
            string query = "";
            string filePath = "C:\\Dialer Team Back-End Database\\DialerTeam_be.accdb";
            DateTime targetDate = DateTime.Parse(recordDateES.ToString());

            string massCellString = "MASSCellRecords = @massCellRecords, MASSCellDials = @massCellDials, MASSCellSaturation = @massCellSaturation," +
                " MASSCellPercentVolume = @massCellPercentVolume, MASSCellPassPenetration = @massCellPassPenetration, MASSCellTotalPassPenFactor =  @massCellTotalPassPenFactor";
            string miCellString = "MICellRecords = @miCellRecords, MICellDials = @miCellDials, MICellSaturation = @miCellSaturation," +
                " MICellPercentVolume = @miCellPercentVolume, MICellPassPenetration = @miCellPassPenetration, MICellTotalPassPenFactor =  @miCellTotalPassPenFactor";
            string allString = "AllRecords = @allRecords, AllDials = @allDials, AllSaturation = @allSaturation," +
                " AllPercentVolume = @allPercentVolume, AllPassPenetration = @allPassPenetrationOne, AllTotalPassPenFactor =  @allTotalPassPenFactorOne," +
                " AllPassPenetrationTwo = @allPassPenetrationTwo, AllTotalPassPenFactorTwo =  @allTotalPassPenFactorTwo," +
                " AllPassPenetrationThree = @allPassPenetrationThree, AllTotalPassPenFactorThree =  @allTotalPassPenFactorThree";
            string massString = "MASSRecords = @massRecords, MASSDials = @massDials, MASSSaturation = @massSaturation," +
                " MASSPercentVolume = @massPercentVolume, MASSPassPenetration = @massPassPenetration, MASSTotalPassPenFactor =  @massTotalPassPenFactor";
            string nhString = "NHRecords = @nhRecords, NHDials = @nhDials, NHSaturation = @nhSaturation," +
                " NHPercentVolume = @nhPercentVolume, NHPassPenetration = @nhPassPenetration, NHTotalPassPenFactor =  @nhTotalPassPenFactor";
            string nonContString = "NonContRecords = @nonContRecords, NonContDials = @nonContDials, NonContSaturation = @nonContSaturation," +
                " NonContPercentVolume = @nonContPercentVolume, NonContPassPenetration = @nonContPassPenetration, NonContTotalPassPenFactor =  @nonContTotalPassPenFactor";
            string orString = "ORRecords = @orRecords, ORDials = @orDials, ORSaturation = @orSaturation," +
                " ORPercentVolume = @orPercentVolume, ORPassPenetration = @orPassPenetration, ORTotalPassPenFactor =  @orTotalPassPenFactor";
            string combinedString = "CombinedRecords = @combinedRecords, CombinedDials = @combinedDials, CombinedSaturation = @combinedSaturation," +
                " CombinedPassPenetration = @combinedPercentWorkedOne," +
                " CombinedPassPenetrationTwo = @combinedPercentWorkedTwo," +
                " CombinedPassPenetrationThree =  @combinedPercentWorkedThree";

            query = "UPDATE ESDialsPerList SET " + massCellString + ", " + miCellString + ", " + allString + ", " + massString + ", " +
                nhString + ", " + nonContString + ", " + orString + ", " + combinedString +
                " WHERE CallDate = #" + targetDate.ToString() + "#";

            WriteEarlyStageData(filePath, query);
        }
        else if (departmentSelector.SelectedIndex == 3)
        {

        }
        else if (departmentSelector.SelectedIndex == 4)
        {

        }
    }

    public void WriteEarlyStageData(string filePath, string query)
    {
        string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;" +
            @"Data Source=" + filePath + ";" +
            @"User Id=;Password=;";

        using (OleDbConnection connection = new OleDbConnection(connectionString))
        using (OleDbCommand command = new OleDbCommand(query, connection))
        {
            try
            {
                connection.Open();
                command.Parameters.AddWithValue("@massCellRecords", Int32.Parse(massCellRecords.Text));
                command.Parameters.AddWithValue("@massCellDials", Int32.Parse(massCellDials.Text));
                command.Parameters.AddWithValue("@massCellSaturation", Double.Parse(massCellSaturation.Text.Replace("%","")));
                command.Parameters.AddWithValue("@massCellPercentVolume", Double.Parse(massCellPercentTotal.Text.Replace("%","")));
                command.Parameters.AddWithValue("@massCellPassPenetration", Double.Parse(massCellPercentWorked.Text));
                command.Parameters.AddWithValue("@massCellTotalPassPenFactor", Double.Parse(massCellPassPercent.Text));

                command.Parameters.AddWithValue("@miCellRecords", Int32.Parse(miCellRecords.Text));
                command.Parameters.AddWithValue("@miCellDials", Int32.Parse(miCellDials.Text));
                command.Parameters.AddWithValue("@miCellSaturation", Double.Parse(miCellSaturation.Text.Replace("%","")));
                command.Parameters.AddWithValue("@miCellPercentVolume", Double.Parse(miCellPercentTotal.Text.Replace("%","")));
                command.Parameters.AddWithValue("@miCellPassPenetration", Double.Parse(miCellPercentWorked.Text));
                command.Parameters.AddWithValue("@miCellTotalPassPenFactor", Double.Parse(miCellPassPercent.Text));

                command.Parameters.AddWithValue("@allRecords", Int32.Parse(allRecords.Text));
                command.Parameters.AddWithValue("@allDials", Int32.Parse(allDials.Text));
                command.Parameters.AddWithValue("@allSaturation", Double.Parse(allSaturation.Text.Replace("%","")));
                command.Parameters.AddWithValue("@allPercentVolume", Double.Parse(allPercentTotal.Text.Replace("%","")));
                command.Parameters.AddWithValue("@allPassPenetrationOne", Double.Parse(allPercentWorkedOne.Text));
                command.Parameters.AddWithValue("@allTotalPassPenFactorOne", Double.Parse(allPassPercentOne.Text));
                command.Parameters.AddWithValue("@allPassPenetrationTwo", Double.Parse(allPercentWorkedTwo.Text));
                command.Parameters.AddWithValue("@allTotalPassPenFactorTwo", Double.Parse(allPassPercentTwo.Text));
                command.Parameters.AddWithValue("@allPassPenetrationThree", Double.Parse(allPercentWorkedThree.Text));
                command.Parameters.AddWithValue("@allTotalPassPenFactorThree", Double.Parse(allPassPercentThree.Text));

                command.Parameters.AddWithValue("@massRecords", Int32.Parse(massRecords.Text));
                command.Parameters.AddWithValue("@massDials", Int32.Parse(massDials.Text));
                command.Parameters.AddWithValue("@massSaturation", Double.Parse(massSaturation.Text.Replace("%","")));
                command.Parameters.AddWithValue("@massPercentVolume", Double.Parse(massPercentTotal.Text.Replace("%","")));
                command.Parameters.AddWithValue("@massPassPenetration", Double.Parse(massPercentWorked.Text));
                command.Parameters.AddWithValue("@massTotalPassPenFactor", Double.Parse(massPassPercent.Text));

                command.Parameters.AddWithValue("@nhRecords", Int32.Parse(nhRecords.Text));
                command.Parameters.AddWithValue("@nhDials", Int32.Parse(nhDials.Text));
                command.Parameters.AddWithValue("@nhSaturation", Double.Parse(nhSaturation.Text.Replace("%","")));
                command.Parameters.AddWithValue("@nhPercentVolume", Double.Parse(nhPercentTotal.Text.Replace("%","")));
                command.Parameters.AddWithValue("@nhPassPenetration", Double.Parse(nhPercentWorked.Text));
                command.Parameters.AddWithValue("@nhTotalPassPenFactor", Double.Parse(nhPassPercent.Text));

                command.Parameters.AddWithValue("@nonContRecords", Int32.Parse(nonContRecords.Text));
                command.Parameters.AddWithValue("@nonContDials", Int32.Parse(nonContDials.Text));
                command.Parameters.AddWithValue("@nonContSaturation", Double.Parse(nonContSaturation.Text.Replace("%","")));
                command.Parameters.AddWithValue("@nonContPercentVolume", Double.Parse(nonContPercentTotal.Text.Replace("%","")));
                command.Parameters.AddWithValue("@nonContPassPenetration", Double.Parse(nonContPercentWorked.Text));
                command.Parameters.AddWithValue("@nonContTotalPassPenFactor", Double.Parse(nonContPassPercent.Text));

                command.Parameters.AddWithValue("@orRecords", Int32.Parse(orRecords.Text));
                command.Parameters.AddWithValue("@orDials", Int32.Parse(orDials.Text));
                command.Parameters.AddWithValue("@orSaturation", Double.Parse(orSaturation.Text.Replace("%","")));
                command.Parameters.AddWithValue("@orPercentVolume", Double.Parse(orPercentTotal.Text.Replace("%","")));
                command.Parameters.AddWithValue("@orPassPenetration", Double.Parse(orPercentWorked.Text));
                command.Parameters.AddWithValue("@orTotalPassPenFactor", Double.Parse(orPassPercent.Text));

                command.Parameters.AddWithValue("@combinedRecords", Int32.Parse(combinedRecords.Text));
                command.Parameters.AddWithValue("@combinedDials", Int32.Parse(combinedDials.Text));
                command.Parameters.AddWithValue("@combinedSaturation", Double.Parse(combinedSaturation.Text.Replace("%","")));
                command.Parameters.AddWithValue("@combinedPercentWorkedOne", Double.Parse(combinedPercentWorkedOne.Text));
                command.Parameters.AddWithValue("@combinedPercentWorkedTwo", Double.Parse(combinedPercentWorkedTwo.Text));
                command.Parameters.AddWithValue("@combinedPercentWorkedThree", Double.Parse(combinedPercentWorkedThree.Text));

                command.ExecuteNonQuery();                    

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }

【问题讨论】:

  • 你在 targetDate.ToShortDateString() 中得到什么值?
  • 您是否在 Access DB 本身中运行过相同的查询?这使您可以确定 Access 期望日期列的格式。
  • 我已在 Access 中完成此操作,预期格式为 #05/02/2016#。所有这一切的原因是我正在使用 VBA 转换现有的 Access 数据库,以便与 C# 前端一起使用。至于targetDate.ToShortDateString()的值,它给出5/2/2016

标签: c# wpf ms-access datatable oledb


【解决方案1】:

为什么不是参数化查询?

string queryString = "SELECT * FROM ESDialsPerList WHERE CallDate = @callDate";
OleDbCommand oleCmd = new OleDbCommand(queryString);
oleCmd.Parameters.Add("@callDate", OleDbType.Date).Value = targetDate;

方法签名中的一个小改动也可以接受 OleDbCommand 代替字符串

public void UpdateEarlyStageData(string filePath, OleDbCommand queryCommand)
{
    //Connection string initializer
    using (OleDbConnection connection = new OleDbConnection("connectionString"))
    {
        queryCommand.Connection = connection;
        using (OleDbDataAdapter adapter = new OleDbDataAdapter(queryCommand))
        {
            System.Data.DataTable table = new System.Data.DataTable();
            adapter.Fill(table);
            // assignment operations
        }
    }
}

【讨论】:

  • 这也不起作用,它给出了与上面相同的 InvalidOperation 异常。我尝试将一个 DateTime 变量放入 targetDate 和一个转换为 ToShortDateString() 的字符串,结果都一样。
【解决方案2】:

您只需要在将日期值转换为字符串表达式时强制使用非本地化格式:

string queryString = "SELECT * FROM ESDialsPerList WHERE CallDate = #" + DateTime.Today.ToString("yyyy'/'MM'/'dd") + "#";
    string 

结果字符串将是 Access SQL 接受的#2016/05/02#

【讨论】:

  • Access 也会接受#05/02/2016#,事实上,这是首选符号。通过在 VBA 模块中粘贴 #2016/05/02#(更好:ISO notation #2016-05-02#)自己尝试一下,它会自动更正为 #5/2/2016#。然而,OP 的问题可能是由于提供者不了解 Access 用于日期的标签,所以所有这些可能都没有抓住重点。
  • 这确实会导致相同的问题,如果完全按照上面发布的方式完成,则 InvalidOperationException,如果我添加额外的斜杠以避免“除法”,则会出现 OleDbException。
  • 那么您的问题可能与其他问题有关。
猜你喜欢
  • 2014-12-26
  • 2019-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
相关资源
最近更新 更多