2013-02-03 29 views
3

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

So这里是正在使用的实际命令

EDIT 2013年2月2日 - 下午9点十分 的command.ExecuteNonQuery是 所述的connectionString以及指令在数据访问类构造

定义)命名的ExecuteNonQuery(方法内
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"/>

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

编辑2013年2月2日 - 9:10 PM 功能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(颜色)
  • “数据\ IMAGES \ Edit_000000.jpg”(图片)
  • 740(ID)

即ID在数据库中确实存在并且在查询执行后没有改变。

编辑2013年2月2日 - 9:10 PM 我不知道如何检查该数据库实际上是被更新,我能想到的唯一的事情是,使用相同的连接字符串和连接对象我做一个具有相同ExecuteNonquery方法的insert语句,它在我正在查看的数据库中工作。和update语句工作得很好,像这样(不带参数):

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

编辑2013年2月2日 - 下午九时41 我已经使用everything.exe搜索我的电脑上的所有数据。 accdb文件在我的电脑上,除了原始文件,我没有发现任何实际的.accdb文件,但是我确实发现了这些.lnk文件,我不相信它们可以改变这个过程,但是我仍然会提及它

data.accdb。 LNK

+0

很难告诉你在每个UpDate Param中做什么查询你在哪里执行非查询命令..你能更好地清理这个例子,并显示代码不工作的完整代码...不是代码工作.. – MethodMan

+0

你确定你要检查数据在正确的数据库中?我只是这样说,因为你可能正在查看文件的副本 – PhoenixReborn

+0

我会在'command.ExecuteNonQuery();'处设置一个断点并检查命令参数设置是否正确 –

回答

0

你想要做的是我过去也做过的事情,但允许编辑连接到OleDB(如Access,Visual FoxPro等),SQL服务器,SyBase SQLAnywhere,也许我的实施可能会帮助你。首先,你将用于在一个公共接口上连接工作的每个元素,例如IDbConnection,IDbCommand,IDbParameter等。

以下是我发布的一小段内容,连接类型。我已经剥离了一堆,并没有真正测试这个剥离的版本,但它应该是一个很好的基准,让你运行。

前提是基线“MyConnection”几乎像一个抽象,但具有属性和一些“常见”的方法,将存在于任何子类定义下。由此,每个函数和参数类型都基于“I”接口,而不是特定的。但是,每个派生将创建它自己的适当类型。这消除了“一切”的需要。希望这可以帮助您随着数据访问层的发展。

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命令(它会返回正确的类型,并自动附加到其相应的“连接句柄”对象,准备文本,添加参数,执行它。