本文讨论数据表记录的更新和删除操作,并实现相关组件,示例以MySQL数据库为主,相关准备知识可以参考作者个人网站资源。
《MySQL数据库应用》合集网址:http://caohuayu.com/article/Group.aspx?id=3
《数据添加、更新和删除》文章网址:http://caohuayu.com/article/Article.aspx?id=a261006
首先来看数据更新操作的接口类型,如下面的代码(cfx/data/tUpdate.cs)。
using System.Collections.Generic; namespace cfx.data { public interface tUpdate { string CnnStr { get; } string Table { get; } tUpdate ClearData(); tUpdate AddData(string name, object value); tUpdate AddData(Dictionary<string, object> data); tUpdate AddData(tPairList data); tUpdate SetCond(tCond cond); tUpdate SetCond(string condSql); long Update(); } // 其它代码 }
代码中定义了tUpdate接口类型,成员包括:
接下来是更新操作基类的实现,如下面的代码(cfx/data/tUpdate.cs)。
using System.Collections.Generic; namespace cfx.data { // 其它代码 public abstract class tUpdateBase : tUpdate { protected string myCnnStr; protected string myTable; protected tPairList myData = tPairList.Create(); protected tCond myCond = null; // public tUpdateBase(string cnnstr,string table) { myCnnStr = cnnstr; myTable = table; } // public string CnnStr { get { return myCnnStr; } } public string Table { get { return myTable; } } // public tUpdate ClearData() { myData.Clear(); return this; } // public tUpdate AddData(string name, object value) { myData.Add(name, value); return this; } // public tUpdate AddData(Dictionary<string, object> data) { if (data == null) return this; foreach(string k in data.Keys){ myData.Add(k, data[k]); } return this; } public tUpdate AddData(tPairList data) { myData.AddRange(data); return this; } // public tUpdate SetCond(tCond cond) { myCond = cond; return this; } // public tUpdate SetCond(string condSql) { myCond = tCond.Direct(condSql); return this; } // public abstract long Update(); } }
代码中,tUpdateBase类定义为抽象,并实现tUpdate接口。类中首先定义几个受保护(protected)字段,分别是:
接下来是构造函数,参数需要指定数据库连接字符串和操作数据表名称,并分别保存到myCnnStr和myTable字段。
除了Update()方法,tUpdate接口成员在tUpdateBase类中都已实现,其中,需要更新的数据会添加到myData对象,更新条件会保存到myCond对象。
下面的代码(cfx/data/mysql/tMySqlUpdate.cs),使用tMySqlUpdate类实现MySQL数据库表记录的更新操作。
using System.Collections.Generic; using System.Text; using MySql.Data.MySqlClient; namespace cfx.data.mysql { public class tMySqlUpdate:tUpdateBase { public tMySqlUpdate(string cnnstr, string table) : base(cnnstr, table) { } // public static tMySqlUpdate Create(string cnnstr,string table) { return new tMySqlUpdate(cnnstr, table); } // public override long Update() { try { List<object> condArg; string sql = GetUpdateSql(out condArg); if (sql.Length == 0) return -1001; using(MySqlConnection cnn = new MySqlConnection(myCnnStr)) { cnn.Open(); MySqlCommand cmd = cnn.CreateCommand(); cmd.CommandText = sql; for (int i = 0; i < myData.Count; i++) cmd.Parameters.AddWithValue("?data" + i, myData[i].Value); for (int i = 0; i < condArg.Count; i++) cmd.Parameters.AddWithValue("?cond" + i, condArg[i]); return cmd.ExecuteNonQueryAsync().Result; } } catch { return -1000; } } // 生成update语句 protected string GetUpdateSql(out List<object> condArg) { string condSql = tMySqlCondBuilder.Get(myCond, out condArg); if (condSql.Length == 0) return ""; // if (myCnnStr == null || myCnnStr.Length == 0 || myTable == null || myTable.Length == 0 || myData.Count == 0) return ""; // StringBuilder sb = new StringBuilder(512); sb.AppendFormat("update `{0}` set `{1}`=?data0", myTable, myData[0].Name); for(int i = 1; i < myData.Count; i++) { sb.AppendFormat(",`{0}`=?data{1}", myData[i].Name, i); } sb.Append(" where "); sb.Append(condSql); return sb.ToString(); } // } }
tMySqlUpdate类继承于tUpdateBase类,构造函数通过基类构造函数实现,需要指定数据库连接字符串和表名;Create()静态方法会返回tMySqlUpdate对象,参数也需要指定数据库连接字符串和表名。
GetUpdateSql()方法用于创建update语句,并通过输出参数condArg带出条件的参数数据。方法中会对更新操作所需的数据进行判断,不满足时返回空字符串,这里不允许无条件更新,当条件语句为空时方法也会返回空字符串。下面是创建update语句的格式:
update `表名` set `数据字段1`=?data0,`数据字段2`=?data1,`数据字段3`=?data2,... where <条件>
其中,<条件>语句由tMySqlCondBuilder类生成,所需参数数据由输出参数condArg带出,应注意条件中的参数约定使用?定义,名称为cond加从0开始的序号。
Update()方法中,首先会生成update语句,如果语句为空字符串则返回-1001;接下来会执行更新操作,并返回影响的记录数量。
下面的代码,我们在Program.cs文件中测试tMySqlUpdate类的应用。
using System; using cfx.data; using cfx.data.mysql; namespace csfx_demo { class Program { static void Main(string[] args) { string cnnstr = tMySqlHelper.GetCnnStr( "127.0.0.1", "cdb_cs1", "root", "DEV_Test123456", 3306); // long result = tMySqlUpdate.Create(cnnstr, "t1") .AddData("f1", "用户1") .SetCond(tCond.Equal("f1", "user01")) .Update(); Console.WriteLine(result); } } }
成功执行操作后会返回大于等于0的整数,即修改记录的数量。出错时会返回小于0的整数。
数据删除操作相对简单,其接口和基类实现如下(cfx/data/tDelete.cs)。
namespace cfx.data { public interface tDelete { string CnnStr { get; } string Table { get; } tDelete SetCond(tCond cond); tDelete SetCond(string condSql); long Delete(); } // public abstract class tDeleteBase : tDelete { protected string myCnnStr; protected string myTable; protected tCond myCond; // public tDeleteBase(string cnnstr,string table) { myCnnStr = cnnstr; myTable = table; } // public string CnnStr { get { return myCnnStr; } } public string Table { get { return myTable; } } public tDelete SetCond(tCond cond) { myCond = cond; return this; } // public tDelete SetCond(string condSql) { myCond = tCond.Direct(condSql); return this; } // public abstract long Delete(); } }
tDelete接口中的成员包括:
tDeletaBase类实现了tDelete接口,其中,首先定义了几个字段:
tDeleteBase()构造函数需要指定数据库连接字符串和表名称,并分别保存到myCnnStr和myTable字段;接下来的SetCond()方法,会将删除条件保存到myCond对象。
下面的代码(cfx/data/mysql/tMySqlDelete.cs),使用tMySqlDelete类实现了MySQL数据库表数据的删除操作。
using System.Collections.Generic; using System.Text; using MySql.Data.MySqlClient; namespace cfx.data.mysql { public class tMySqlDelete : tDeleteBase { public tMySqlDelete(string cnnstr, string table) : base(cnnstr, table) { } // public static tMySqlDelete Create(string cnnstr,string table) { return new tMySqlDelete(cnnstr, table); } // public override long Delete() { try { List<object> condArg; string sql = GetDeleteSql(out condArg); if (sql.Length == 0) return -1001; using(MySqlConnection cnn = new MySqlConnection(myCnnStr)) { cnn.Open(); MySqlCommand cmd = cnn.CreateCommand(); cmd.CommandText = sql; for (int i = 0; i < condArg.Count; i++) cmd.Parameters.AddWithValue("?cond" + i, condArg[i]); return cmd.ExecuteNonQueryAsync().Result; } } catch { return -1000; } } // protected string GetDeleteSql(out List<object> condArg) { string condSql = tMySqlCondBuilder.Get(myCond, out condArg); if (condSql.Length==0) return ""; // if (myCnnStr == null || myCnnStr.Length == 0 || myTable == null || myTable.Length == 0) return ""; // StringBuilder sb = new StringBuilder(256); sb.AppendFormat("delete from `{0}` where {1}", myTable, condSql); return sb.ToString(); } // } }
代码中,构造函数和Create()静态方法用于创建tMySqlDelete类的实例,参数需要数据库连接字符串和表名。
GetDeleteSql()方法用于生成delete语句,这里同样不允许无条件删除操作;当条件或其它操作要素不满足时会返回空字符串。
Delete()方法会执行删除操作,并返回删除的记录数量。出错时会返回小于0的整数。
下面的代码,在Program.cs文件中测试tMySqlDelete类的应用。
using System; using cfx.data; using cfx.data.mysql; namespace csfx_demo { class Program { static void Main(string[] args) { string cnnstr = tMySqlHelper.GetCnnStr( "127.0.0.1", "cdb_cs1", "root", "DEV_Test123456", 3306); // long result = tMySqlDelete.Create(cnnstr, "t1") .SetCond(tCond.Equal("f1", "用户1")) .Delete(); Console.WriteLine(result); } } }
执行代码会删除t1表中f1字段等于“用户1”的记录,正确执行会显示删除的记录数量,应该是大于或等于0的整数(删除的记录数量),执行错误时会返回小于0的整数。
首先是SQL Server数据库表数据更新操作,使用tSqlUpdate类实现,如下面的代码(cfx/data/sql/tSqlUpdate.cs)。
using System.Collections.Generic; using System.Text; using System.Data.SqlClient; namespace cfx.data.sql { public class tSqlUpdate:tUpdateBase { public tSqlUpdate(string cnnstr, string table) : base(cnnstr, table) { } // public static tSqlUpdate Create(string cnnstr,string table) { return new tSqlUpdate(cnnstr, table); } // public override long Update() { try { List<object> condArg; string sql = GetUpdateSql(out condArg); if (sql.Length == 0) return -1001; using(SqlConnection cnn = new SqlConnection(myCnnStr)) { cnn.Open(); SqlCommand cmd = cnn.CreateCommand(); cmd.CommandText = sql; for (int i = 0; i < myData.Count; i++) cmd.Parameters.AddWithValue("@data" + i, myData[i].Value); for (int i = 0; i < condArg.Count; i++) cmd.Parameters.AddWithValue("@cond" + i, condArg[i]); return cmd.ExecuteNonQueryAsync().Result; } } catch { return -1000; } } // 生成update语句 protected string GetUpdateSql(out List<object> condArg) { string condSql = tSqlCondBuilder.Get(myCond, out condArg); if (condSql.Length == 0) return ""; // if (myCnnStr == null || myCnnStr.Length == 0 || myTable == null || myTable.Length == 0 || myData.Count == 0) return ""; // StringBuilder sb = new StringBuilder(512); sb.AppendFormat("update [{0}] set [{1}]=@data0", myTable, myData[0].Name); for(int i = 1; i < myData.Count; i++) { sb.AppendFormat(",[{0}]=@data{1}", myData[i].Name, i); } sb.Append(" where "); sb.Append(condSql); return sb.ToString(); } // } }
下面的代码(cfx/data/sql/tSqlDelete.cs)是SQL Server数据库表数据删除操作,使用tSqlDelete类实现。
using System.Collections.Generic; using System.Text; using System.Data.SqlClient; namespace cfx.data.sql { public class tSqlDelete : tDeleteBase { public tSqlDelete(string cnnstr, string table) : base(cnnstr, table) { } // public static tSqlDelete Create(string cnnstr,string table) { return new tSqlDelete(cnnstr, table); } // public override long Delete() { try { List<object> condArg; string sql = GetDeleteSql(out condArg); if (sql.Length == 0) return -1001; using(SqlConnection cnn = new SqlConnection(myCnnStr)) { cnn.Open(); SqlCommand cmd = cnn.CreateCommand(); cmd.CommandText = sql; for (int i = 0; i < condArg.Count; i++) cmd.Parameters.AddWithValue("@cond" + i, condArg[i]); return cmd.ExecuteNonQueryAsync().Result; } } catch { return -1000; } } // protected string GetDeleteSql(out List<object> condArg) { string condSql = tSqlCondBuilder.Get(myCond, out condArg); if (condSql.Length==0) return ""; // if (myCnnStr == null || myCnnStr.Length == 0 || myTable == null || myTable.Length == 0) return ""; // StringBuilder sb = new StringBuilder(256); sb.AppendFormat("delete from [{0}] where {1}", myTable, condSql); return sb.ToString(); } // } }
tSqlUpdate和tSqlDelete类中,SQL Server数据库对象名称使用一对方括号定义,参数使用@符号定义,并使用了cfx.data.sql命名空间和System.Data.SqlClient命名空间的资源,这里不再详细说明。