上篇介绍了ORMapping的一个大体结构,看起来很简单,基本没有什么复杂的设计模式之说,关于接口类的实现与MEF的管理在上篇都介绍过,这篇就开始介绍ORMapping中的细节点了,当然还是围绕对数据库的操作(增删查改)来讲,我这就只介绍Insert command吧,其它的都一样。
有朋友就会问既然是ORMapping,那肯定得有一套完整的映射关于与操作逻辑,关于映射关系的介绍之前都简单介绍过了,比较抽象,现在在这里就以怎样生成Insert Command来介绍ORMapping的核心部分。
在IORMapper的接口中我定义了一个Insert方法,从名称上来看,当然是作数据库的插入数据来用的。
接下来我会在ORMapper类中实现该方法:
public void Insert<T>(T obj)
{
}
我们既然想作一个数据库的插入操作,那我们总会有一个sqlconnection 和一个sqlcommand, 当然这不是主要的,主要的就是sqlcommand里的commandText,这个怎么来呢?这就涉及到我之前定义的Model结构和那些Attribute,不明白的可以看前面几篇里有介绍。
我在这就贴上我完整的Inter方法:
public void Insert<T>(T obj)
{
using (IDbConnection conn = NewConnection()) // 这里有个自定义的NewConnection的方法,我就不写了,你们按照自己的需求实现
{
try
{
conn.Open();
}
catch (SqlException sqlEx)
{
throw new DbConnectionException(conn.Database, sqlEx.Message, sqlEx);
}
var InsertCMD = GetInsertCommands(obj, conn); //大家可能会注意到这里有个方法,这就是去生成sqlcommand的,下面我会详细说到
foreach (var command in InsertCMD)
{
using (command)
{
command.ExecuteNonQuery();
}
}
}
下面就介绍我们怎么去生成这个sqlcommand,这里我定义一些重载的GetInsertCommands方法
public List<IDbCommand> GetInsertCommands<T>(T obj, IDbConnection connection)
{
return GetInsertCommands(obj, ColumnCollectionInfo.GetInfo(obj.GetType()), connection);
}
private List<IDbCommand> GetInsertCommands(Object obj, ColumnCollectionInfo dataInfo, IDbConnection connection)
{
List<IDbCommand> result = new List<IDbCommand>();
if (dataInfo.BaseInfo != null)
{
result.AddRange(GetInsertCommands(obj, dataInfo.BaseInfo, connection)); //这里是添加Model中基类里的数据插入操作,如果你对Model结构由疑问可以随时联系我和我交流,这边我可能不再作深入补充
}
if (!string.IsNullOrEmpty(dataInfo.Name)) //这里生成的是当然Table的插入的command
{
IDbCommand command = connection.CreateCommand();
command.CommandText = GetInsertStatement(obj, dataInfo, command);
result.Add(command);
}
var manyToManyInfos = dataInfo.Collections.Values.Cast<CollectionInfo>().Where(t => t.CollectionType == CollectionType.ManyToMany); //这边是生成ManyToMany的关系数据的中间表数据插入Command
foreach (CollectionInfo info in manyToManyInfos)
{
result.AddRange(GetInsertCommands(obj, dataInfo, info, connection));
}
return result;
}
private List<IDbCommand> GetInsertCommands(Object obj, ColumnCollectionInfo dataInfo, CollectionInfo collectionInfo, IDbConnection connection)
{
List<IDbCommand> result = new List<IDbCommand>();
IEnumerable targets = collectionInfo.GetValue(obj);
if (targets != null)
{
foreach (var target in targets)
{
IDbCommand command = connection.CreateCommand();
command.CommandText = GetInsertStatement(obj, target, dataInfo, collectionInfo, command);
result.Add(command);
}
}
return result;
}
private string GetInsertStatement(Object src, Object target, ColumnCollectionInfo srcDataInfo, CollectionInfo collectionInfo, IDbCommand command)
{
var targetDataInfo = ColumnCollectionInfo.GetInfo(target.GetType());
int index = 0;
List<string> values = new List<string>();
foreach (ColumnInfo column in srcDataInfo.PrimaryKeys.Values)
{
string parameterName = string.Format(UpdateSqlValueParameter, index++);
values.Add(parameterName);
AddParameter(column, parameterName, column.GetValue(src), command);
}
foreach (ColumnInfo column in targetDataInfo.PrimaryKeys.Values)
{
string parameterName = string.Format(UpdateSqlValueParameter, index++);
values.Add(parameterName);
AddParameter(column, parameterName, column.GetValue(target), command);
}
return string.Format(InsertSql,GetTableName(collectionInfo.IntermediateTableName),collectionInfo.MapSourceKey + Comma + collectionInfo.MapTargetKey,string.Join(Comma, values));
}
private string GetInsertStatement(Object obj, ColumnCollectionInfo dataInfo, IDbCommand command)
{
int index = 0;
List<string> values = new List<string>();
foreach (ColumnInfo column in dataInfo.PrimaryKeys.Values)
{
string parameterName = string.Format(UpdateSqlValueParameter, index++);
values.Add(parameterName);
AddParameter(column, parameterName, column.GetValue(obj), command);
}
foreach (ColumnInfo column in dataInfo.Columns.Values)
{
if (!column.ReadOnly)
{
string parameterName = string.Format(UpdateSqlValueParameter, index++);
values.Add(parameterName);
AddParameter(column, parameterName, column.GetValue(obj), command);
}
}
return string.Format(InsertSql, GetTableName(dataInfo.Name), dataInfo.GetSelectOrInsertColumns(Comma, true, Dot, LeftSquare, RightSquare, true), string.Join(Comma, values));
}
这三个方法估计你们看起来会很有疑问,这里面怎么会有一些不知道的dataInfo的一些东西,看了前面的朋友也就会发现,这里就开始用到了我们在之前定义的很多Attribute,
这些东西我本来想放在介绍这个之前来介绍的,我觉得先介绍Command的生成过程再来介绍数据库信息的获取这样会更明了,容易理解一点。下篇我会介绍那些关于数据库结构的DataInfo是怎样从Model中获取。
代码看起来可能会有些头晕,细心的朋友我相信会有收获的,这里我就不把我的源代码贴出来,我觉得这样的意义不大,有什么疑问随时可以和我联系,微信号:hwy425