3

我正在尝试更新访问文件 (.accdb) 中的记录。我正在尝试使用 .net OleDbCommand 和 OleDbParameters。我还尝试使用通用模型并将所有命令和参数存储在 System.Data.Common 抽象等效项中,以便我可以轻松切换到 SQL Server(我确实计划这样做)

所以这是实际使用的命令

编辑 2/2/2013 - 晚上 9:10 command.ExecuteNonQuery 在名为 ExecuteNonQuery() 的方法内,connectionString 和 command 在 DataAccess 类构造函数中定义

public class DataAccess
{

    private string connectionString;
    private DbConnection connection;
    private DbCommand command;
    private DbDataReader reader;
    private DataTable data;

    public DataAccess()
    {
        connectionString = ConfigurationSettings.AppSettings["ConnectionString"];

        switch (ConfigurationSettings.AppSettings["DataBaseType"])
        {
            case "oledb":
                connection = new OleDbConnection(connectionString);
                command = new OleDbCommand(string.Empty, (OleDbConnection)connection);
                break;
            case "SQL":                 
                connection = new SqlConnection(connectionString);
                command = new SqlCommand(string.Empty, (SqlConnection)connection);
                break;
            default:
                break;
        }

    }

    public void ExecuteNonQuery(string SQL, params DbParameter[] parameters)
    {
        command.CommandType = CommandType.Text;
        command.CommandText = SQL;
        command.Parameters.AddRange(parameters);

        try
        {
            command.Connection.Open();

            try
            {
                command.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                command.Connection.Close();
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public DbParameter NewParameter(string name, object value)
    {
        DbParameter param;

        switch (ConfigurationSettings.AppSettings["DataBaseType"])
        {
            case "oledb":
                param = new OleDbParameter(name, value);
                break;
            case "SQL":
                param = new SqlParameter(name, value);
                break;
            default:
                param = null;
                break;
        }

        return param;
    }

这些是 App.Config 文件中的属性

<add key="DataBaseType" value="oledb"/>

<add key="ConnectionString" value="Provider=Microsoft.ACE.OLEDB.12.0;Data Source=data.accdb"/>

现在的问题是在更新语句中使用参数时,更新永远不会发生,也永远不会引发错误。这是它的代码。

编辑 2/2/2013 - 晚上 9:10 函数 DataAccess.NewParameter 在第一个代码块中

DALayer.ExecuteNonQuery("UPDATE TileTypes SET Title = @Title, Picture = @Picture, Color = @Color WHERE ID = @ID",
 DALayer.NewParameter("@Title", titleTextBox.Text.Trim()),
 DALayer.NewParameter("@Picture", typePictureBox.ImageLocation),
 DALayer.NewParameter("@Color", colorButton.BackColor.ToArgb()),
 DALayer.NewParameter("@ID", id));

我已将查询复制到访问中,并将所有参数名称替换为传递的实际数据,这很好用。我尝试将 SQL 文本中的所有参数替换为 ? 性格没有影响。我尝试将所有表名和列名括在括号 [] 中也没有效果。

  • ID 是一个自动编号字段
  • 标题是一个文本字段
  • 图片是一个文本字段
  • 颜色是一个长整数字段

这是一些直接从 Visual Studio 监视窗口中的参数复制的示例数据:

  • “编辑”(标题)
  • -1(颜色)
  • “数据\图像\Edit_000000.jpg”(图片)
  • 740(身份证)

该 ID 确实存在于数据库中,并且在执行查询后未更改。

编辑 2/2/2013 - 晚上 9:10 我不确定如何检查哪个数据库实际上正在更新,我唯一能想到的是使用相同的连接字符串和连接对象我使用相同的 ExecuteNonquery 执行了插入语句方法,它在我正在查看的数据库中工作。并且更新语句就像这样工作得很好(没有参数):

DALayer.ExecuteNonQuery("UPDATE TileTypes SET Title = '" + titleTextBox.Text + 
"', Color = " + colorButton.BackColor.ToArgb() + ", Picture = '" + 
imageLocation + "' WHERE ID = " + id);

编辑 2/2/2013 - 晚上 9:41 我已经使用了everything.exe 在我的计算机上搜索了我计算机上的所有 data.accdb 文件,除了原始文件之外,我没有找到任何实际的 .accdb 文件,但我确实找到了这些 .lnk文件,我不相信他们可以改变这个过程,但我还是会提到它

数据.accdb.LNK

4

1 回答 1

0

您正在尝试做的是我过去也做过的事情,但允许连接到 OleDB(如 Access、Visual FoxPro 等)、SQL-Server、SyBase SQLAnywhere,也许我的实现可能会对您有所帮助。首先,您将用于连接的每个元素都在一个公共接口上工作,例如 IDbConnection、IDbCommand、IDbParameter 等。

下面我发布的是我最初如何构建这种多数据库连接类型的一小部分。我已经剥离了一堆并没有实际测试这个剥离的版本,但它应该是你运行的一个很好的基准。

前提是基线“MyConnection”几乎就像一个抽象,但具有在任何子类定义下都存在的属性和一些“通用”方法。由此可见,每个函数和参数类型都是基于“I”接口的,而不是具体的。但是,每个派生都将创建其 OWN 正确类型。这消除了“案例”一切的需要。希望这对您的数据访问层开发有所帮助。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

// for OleDB (Access, VFP, etc)
using System.Data.OleDb;
// for SQL-Server
using System.Data.SqlClient;

namespace DataMgmt
{
    public class MyConnection
    {
        // no matter the connection to server, it will require some "handle"
        // that is of type "IDbConnection"
        protected IDbConnection sqlConnectionHandle;

        // when querying, ANY query could have an exception that needs to have
        // possible further review for handling
        public Exception LastException
        { get; protected set; }

        // When calling an execute command (select, insert, update, delete), 
        // they all can return how many rows affected
        public int RowsAffectedByQuery
        { get; protected set; }

        // different databases could have different connection strings. Make
        // virtual and throw exception so sub-classed must return proper formatted.
        public virtual string GetConnectionString()
        { throw new Exception("GetConnectionString() method must be overridden."); }

        // each has its own "IDbConnection" type too
        protected virtual IDbConnection SQLConnectionHandle()
        { return sqlConnectionHandle; }

        public virtual IDbCommand GetSQLDbCommand()
        { throw new Exception("GetSQLDbCommand() method must be overridden."); }

        // generic routine to get a data parameter...
        public virtual IDbDataParameter AddDbParmSpecificValue(string ParmName, object UnknownValue)
        { throw new Exception("AddDbParmSpecificValue() method must be overwritten per specific connection."); }

        // generic "Connection" since they are all based on IDbCommand...
        public override bool SQLConnect()
        {
            // pre-blank exception in case remnant from previous activity
            LastException = null;

            if (sqlConnectionHandle.State != System.Data.ConnectionState.Open)
                try
                {
                    // if not open, always make sure we get updated connection string
                    // if ever changed by some other "unknown" condition...
                    sqlConnectionHandle.ConnectionString = GetConnectionString();
                    sqlConnectionHandle.Open();
                }
                catch (Exception ex)
                {
                    // Preserve in generic sqlException" property for analysis OUTSIDE this function
                    LastException = ex;
                }

            // if NOT connected, display message to user and set error code and exception
            if (sqlConnectionHandle.State != System.Data.ConnectionState.Open)
                LastException = new Exception("Unable to open database connection.");

            // return if it IS successful at opening the connection (or was already open)
            return sqlConnectionHandle.State == System.Data.ConnectionState.Open;
        }

        // likewise disconnect could be common
        public void SQLDisconnect()
        {
            if (sqlConnectionHandle != null)
                if (sqlConnectionHandle.State == ConnectionState.Open)
                    sqlConnectionHandle.Close();
        }


        public bool SqlExecNonQuery( IDbCommand SQLCmd, DataTable oTbl)
        {
            // pre-clear exception
            LastException = null;

            // fill the table...
            SQLConnect();
            try
            {
                RowsAffectedByQuery = SQLCmd.ExecuteNonQuery();
            }
            catch (Exception e)
            {
                LastException = e;
                throw e;
            }
            finally
            {
                SQLDisconnect();
            }

            // Its all ok if no exception error
            return LastException == null;
        }

    }


    // Now, build your connection manager per specific type
    public class MyAccessConnection : MyConnection
    {
        public MyAccessConnection()
        {   sqlConnectionHandle =  new OleDbConnection();   }

        public override string GetConnectionString()
        {   return "Your Connection String from AppSettings.. any changes if OleDb vs SQL"; }

        public override IDbCommand GetSQLDbCommand()
        {   return new OleDbCommand( "", (OleDbConnection)sqlConnectionHandle ); }

        public override IDbDataParameter AddDbParmSpecificValue(string ParmName, object UnknownValue)
        {   return new OleDbParameter( ParmName, UnknownValue );    }

    }

    public class MySQLConnection : MyConnection
    {
        public MySQLConnection()
        {   sqlConnectionHandle = new SqlConnection();  }

        public override string GetConnectionString()
        { return "Your Connection String from AppSettings... any alterations needed??? "; }

        public override IDbCommand GetSQLDbCommand()
        { return new SqlCommand ("", (SqlConnection)sqlConnectionHandle); }

        public override IDbDataParameter AddDbParmSpecificValue(string ParmName, object UnknownValue)
        { return new SqlParameter(ParmName, UnknownValue); }
    }



    // Now to implement... pick one... Access or SQL-Server for derivation...
    public class MyDataLayer : MyAccessConnection
    {
        public void SomeSQLCall()
        {
            IDbCommand sqlcmd = GetSQLDbCommand();
            sqlcmd.CommandText = "UPDATE TileTypes SET Title = @Title, "
                                + "Picture = @Picture, "
                                + "Color = @Color "
                                + "WHERE ID = @ID";
            sqlcmd.Parameters.Add( AddDbParmSpecificValue( "@Title", titleTextBox.Text.Trim() ));
            sqlcmd.Parameters.Add( AddDbParmSpecificValue( "@Picture", typePictureBox.ImageLocation) );
            sqlcmd.Parameters.Add( AddDbParmSpecificValue( "@Color", colorButton.BackColor.ToArgb()) );
            sqlcmd.Parameters.Add( AddDbParmSpecificValue(  "@ID", id));

        if( SqlExecNonQuery(sqlcmd))
            // Good to go
            DoSomethingWithTheData;
        else
            // Notify of whatever error thrown....

        }
    }
}

所以.. 正如你所看到的,我的最后一个类特别是从 Access 或 SQL 派生的。然后,我可以创建我的方法来获取数据、调用更新等等。获取一个 SQL 命令(它返回正确的类型并自动附加到其相应的“连接句柄”对象,准备文本,添加参数,执行它。

于 2013-02-04T02:16:45.733 回答