第29课:实现MySQL操作组件(2)
本课将完成支持MySQL数据库的tDb、tInsert、tUpdate和tDelete接口组件。
tDb接口
tDb接口作为构造器组件,可以方便创建各类数据组件对象,接口定义如下。
C# |
public interface tDb
{
string CnnStr { get; }
tJet GetJet();
tTable GetTable(string tableName);
tInsert GetInsert(string tableName,string idName);
tUpdate GetUpdate(string tableName);
tDelete GetDelete(string tableName);
tSelect GetSelect(string source);
tBatch GetBatch(string tableName, string idName);
}
|
支持MySQL数据库tDb接口组件定义为tMySql类,实现如下(/app_code/data/mysql/tMySql.cs)。
C# |
public class tMySql : tDb
{
//
public tMySql(string sCnnStr)
{
CnnStr = sCnnStr;
}
//
public string CnnStr { get; private set; }
//
public tJet GetJet()
{ return new tMySqlJet(CnnStr); }
////
public tTable GetTable(string tableName)
{ return new tMySqlTable(GetJet(), tableName); }
////
public tInsert GetInsert(string tableName, string idName)
{ return new tMySqlInsert(GetJet(), tableName, idName); }
////
public tUpdate GetUpdate(string tableName)
{ return new tMySqlUpdate(GetJet(), tableName); }
////
public tDelete GetDelete(string tableName)
{ return new tMySqlDelete(GetJet(), tableName); }
////
public tSelect GetSelect(string source)
{
return new tMySqlSelect(GetJet(), source);
}
////
public tBatch GetBatch(string tableName, string idName)
{
return new tMySqlBatch(GetJet(), tableName, idName);
}
}
|
项目中的tApp类创建了Db字段(tDb接口类型),定义了项目中的主构造器对象,如下面的代码。
C# |
using System;
using System.Web;
public class tApp
{
public static string CnnStr1 = tMySqlHelper.GetCnnStr(
"cdb_demo", "127.0.0.1", "root", "DEV_Test123456", 3306);
public static tDb Db = new tMySql(CnnStr1);
// 其它代码
}
|
代码中定义访问的数据库为MySQL,相关参数包括:
- 数据库名称为cdb_demo。
- 服务器地址为127.0.0.1,即本机。
- 用户名为root,这是MySQL的默认管理员用户。
- 登录密码为DEV_Test123456。
- 端口使用默认的3306。
应用中,只需要使用tApp.Db对象的相关方法,就可以获取相应的数据库操作组件;比如,操作user_main表的操作类可以使用如下代码获取。
C# |
tInsert ins = tApp.Db.GetInsert("user_main", "userid");
tUpdate upd = tApp.Db.GetUpdate("user_main");
tDelete del = tApp.Db.GetDelete("user_main");
tSelect sel = tApp.Db.GetSelect("user_main");
tDbBatch bat = tApp.Db.GetBatch("user_main","userid");
|
此外,获取tJet对象时,可以使用tApp.Db.GetJet()方法。目前,这些组件还没有实现,可以先让tMySql类中的方法返回null值,在创建组件后再修改为返回具体组件的对象。接下来将实现支持MySQL数据库操作的具体类型,首先从tInsert接口组件开始。
tInsert接口
tInsert接口用于向数据表的添加记录,接口定义如下。
C# |
public interface tInsert
{
tJet Jet { get; }
string TableName { get; }
string IdName { get; }
// Insert方法返回新记录ID
long Insert(tPairList data);
long Insert(params tPair[] data);
long Insert(string fields, string values);
long Insert(params string[] nameValuePair);
}
|
在MySQL数据库中使用tMySqlInsert类实现tInsert接口,基础定义如下(/app_code/data/mysql/tMySqlInsert.cs)。
C# |
using System;
using System.Text;
using MySql.Data.MySqlClient;
public class tMySqlInsert : tInsertBase
{
public tMySqlInsert(tJet jet, string tableName, string idName)
: base(jet, tableName, idName) { }
// 其它代码...
}
|
tMySqlInsert类继承于tInsertBase类,构造函数需要指定MySQL数据库操作的Jet(tJet类型)、TableName和IdName属性数据;并通过继承基类的构造函数指定属性值。
下面的代码重写了Insert(tPairList)方法。
C# |
public override long Insert(tPairList data)
{
try
{
// 生成SQL
StringBuilder sb = new StringBuilder("insert into ", 256);
sb.AppendFormat("`{0}`(`{1}`", TableName, data[0].Name);
StringBuilder sbValue = new StringBuilder(")values(?data_0",128);
//
for (int i = 1; i < data.Count; i++)
{
sb.AppendFormat(",`{0}`", data[i].Name);
sbValue.AppendFormat(",?data_{0}", i);
}
sb.Append(sbValue.ToString());
sb.Append(")");
//
using (MySqlConnection cnn = new MySqlConnection(Jet.CnnStr))
{
cnn.Open();
MySqlCommand cmd = cnn.CreateCommand();
using (MySqlTransaction tran = cnn.BeginTransaction())
{
cmd.CommandText = sb.ToString();
for (int i = 0; i < data.Count; i++)
cmd.Parameters.AddWithValue("?data_" + i.ToString(),
data[i].Value);
IAsyncResult ar = cmd.BeginExecuteNonQuery();
long result = -1000;
if (cmd.EndExecuteNonQuery(ar) == 1)
{
cmd.CommandText = "select @@identity";
cmd.Parameters.Clear();
result= tLng.GetValue(cmd.ExecuteScalar());
tran.Commit();
}
return result;
}
}
}
catch(Exception ex)
{
tLog.E(ex, -1000, "tMySqlInsert.Insert(tPairList)");
return -1000;
}
}
|
方法中首先会生成MySQL数据库使用的insert语句,其中,表名和字段名使用一对重音符号定义的对象格式,而values子句中的参数名使用了?data_0、?data_1、?data_2、……格式。方法生成的insert语句格式如下。
MySQL |
insert into `<表>`(`<字段1>`,`<字段2>`,`<字段3>`,…)
values(?data_0,?data_1,?data_2,…);
|
Insert(tPairList)方法中,使用事务(Transaction)完成新数据的添加工作,并通过select @@identity语句返回新记录的ID字段数据。如果方法返回大于0的整数,则表示数据添加成功。
Insert(tPair[])方法与Insert(tPairList)方法实现相似,如下面的代码。
C# |
public override long Insert(params tPair[] data)
{
try
{
// 生成SQL
StringBuilder sb = new StringBuilder("insert into ", 256);
sb.AppendFormat("`{0}`(`{1}`", TableName, data[0].Name);
StringBuilder sbValue = new StringBuilder(")values(?data_0", 128);
//
for (int i = 1; i < data.Length; i++)
{
sb.AppendFormat(",`{0}`", data[i].Name);
sbValue.AppendFormat(",?data_{0}", i);
}
sb.Append(sbValue.ToString());
sb.Append(")");
//
using (MySqlConnection cnn = new MySqlConnection(Jet.CnnStr))
{
cnn.Open();
MySqlCommand cmd = cnn.CreateCommand();
using (MySqlTransaction tran = cnn.BeginTransaction())
{
cmd.CommandText = sb.ToString();
for (int i = 0; i < data.Length; i++)
cmd.Parameters.AddWithValue("?data_" + i.ToString(),
data[i].Value);
IAsyncResult ar = cmd.BeginExecuteNonQuery();
long result = -1000;
if (cmd.EndExecuteNonQuery(ar) == 1)
{
cmd.CommandText = "select @@identity";
cmd.Parameters.Clear();
result = tLng.GetValue(cmd.ExecuteScalar());
tran.Commit();
}
return result;
}
}
}
catch (Exception ex)
{
tLog.E(ex, -1000, "tMySqlInsert.Insert(tPair[])");
return -1000;
}
}
|
下面的代码是Insert(string,string)方法的实现。
C# |
public override long Insert(string fields, string values)
{
try
{
StringBuilder sb = new StringBuilder(256);
sb.AppendFormat("insert into `{0}`({1}) values({2});",
TableName, fields, values);
using (MySqlConnection cnn = new MySqlConnection(Jet.CnnStr))
{
cnn.Open();
MySqlCommand cmd = cnn.CreateCommand();
using (MySqlTransaction tran = cnn.BeginTransaction())
{
cmd.CommandText = sb.ToString();
IAsyncResult ar = cmd.BeginExecuteNonQuery();
long result = -1000;
if (cmd.EndExecuteNonQuery(ar) == 1)
{
cmd.CommandText = "select @@identity";
cmd.Parameters.Clear();
result = tLng.GetValue(cmd.ExecuteScalar());
tran.Commit();
}
return result;
}
}
}
catch(Exception ex)
{
tLog.E(ex, -1000, "tMySqlInsert.Insert(string,string)");
return -1000;
}
}
|
Insert(string,string)方法中,首先创建insert语句,格式如下。
MySQL |
insert into `<表>`(<fields参数>) values(<values参数>);
|
创建insert语句后,同样通过事务执行,在执行insert语句后返回新记录的ID字段数据;当方法返回大于0的整数时表示数据添加成功。
最后是Insert(string[])方法的实现,如下面的代码。
C# |
public override long Insert(params string[] nameValuePair)
{
try
{
//
if (nameValuePair.Length < 2 || nameValuePair.Length % 2 != 0)
return -1001;
//
StringBuilder sb = new StringBuilder("insert into ", 256);
sb.AppendFormat("`{0}`(`{1}`", TableName, nameValuePair[0]);
StringBuilder sbValue = new StringBuilder(128);
sbValue.AppendFormat(")values({0}", nameValuePair[1]);
for (int i = 2; i < nameValuePair.Length; i += 2)
{
sb.AppendFormat(",`{0}`", nameValuePair[i]);
sbValue.AppendFormat(",{0}", nameValuePair[i + 1]);
}
//
sb.Append(sbValue.ToString());
sb.Append(")");
//
using (MySqlConnection cnn = new MySqlConnection(Jet.CnnStr))
{
cnn.Open();
MySqlCommand cmd = cnn.CreateCommand();
using (MySqlTransaction tran = cnn.BeginTransaction())
{
cmd.CommandText = sb.ToString();
IAsyncResult ar = cmd.BeginExecuteNonQuery();
long result = -1000;
if (cmd.EndExecuteNonQuery(ar) == 1)
{
cmd.CommandText = "select @@identity";
cmd.Parameters.Clear();
result = tLng.GetValue(cmd.ExecuteScalar());
tran.Commit();
}
return result;
}
}
}
catch(Exception ex)
{
tLog.E(ex, -1000, "tMySqlInsert.Insert(string[])");
return -1000;
}
}
|
Insert(string[])方法中的参数每2个为一组,第一个为字段名,第二个为对应的数据;只有方法的参数大于2并且是偶数个时才会执行。和Insert(string,string)方法应用相似,直接使用字段和数据时要注意安全性和语句的通用性问题,特别是用户提交的数据,一般不应直接用于组合SQL语句,而是使用Insert(tPairLsit)或Insert(tPair[])方法,通过参数带入语句所需要的数据。此外,对于文本、二进制和日期时间数据注意使用一对单引号定义,而数值、null值等则直接使用字面量。
下面的代码,我们通过tInsert组件中的Insert(tPairList>方法向user_main表添加一条记录。
C# |
tInsert ins = tApp.Db.GetInsert("user_main", "userid");
tPairList data = tPairList.Get(
tPair.Get("username","user90"),
tPair.Get("userpwd",tStr.Sha256("12345678")),
tPair.Get("email","user90@aaa.bbb"),
tPair.Get("locked",0));
long result = ins.Insert(data);
tWeb.WriteLine(result);
|
下面的代码可以完成同样的工作。
C# |
tInsert ins = tApp.Db.GetInsert("user_main", "userid");
long result = ins.Insert(tPair.Get("username", "user91"),
tPair.Get("userpwd", tStr.Sha256("12345678")),
tPair.Get("email", "user90@aaa.bbb"),
tPair.Get("locked", 0));
tWeb.WriteLine(result);
|
如果字段名和数据内容比较简单,也可以直接使用Insert(string,string)方法添加记录,如下面的代码。
C# |
tInsert ins = tApp.Db.GetInsert("user_main", "userid");
string fields = "username,userpwd,email,locked";
string values = "'user92','"+tStr.Sha256("12345678")+"','user91@aaa.bbb',0";
long result = ins.Insert(fields,values);
tWeb.WriteLine(result);
|
下面使用Insert(string[])方法实现相同的功能。
C# |
tInsert ins = tApp.Db.GetInsert("user_main", "userid");
string[] data = new string[]{
"username", "'user93'",
"userpwd","'"+tStr.Sha256("12345678")+"'",
"email","'user91@aaa.bbb'",
"locked","0"};
long result = ins.Insert(data);
tWeb.WriteLine(result);
|