做自己的ORMapping Framework ---- 第七讲 开始ORMapping之旅,ORMapping 中command怎么生成呢

上篇介绍了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

时间: 2024-12-08 11:33:03

做自己的ORMapping Framework ---- 第七讲 开始ORMapping之旅,ORMapping 中command怎么生成呢的相关文章

做自己的ORMapping Framework ---- 第六讲 开始ORMapping之旅,ORMapping怎么说

这几天公司有点事情,没怎么来这边,现在来这边介绍下ORMapping实现一些什么东西 说到ORMapping,当然少不了的就是对数据库的增删查改,这边的类图我简单弄了下 下面的代码都是我在框架中的源码,这个编辑器很差,贴上来会有点难看,接口里的方法属性都是我平时开发中都会经常用到的,做什么的基本看名称就知道,这里还得说下,代码规范真的很重要,小朋友们写代码时候多注意点. public interface IEntityAccesser { bool Exist<T>(T obj); 存在监测

做自己的ORMapping Framework ---- 第九讲 开始ORMapping之旅,更新库表结构更新架构设计

做一个项目,没有人会把一个数据库设计得那么完善以至于后期不会有任何的改动,能设计这样数据库的人估计在火星上看你写代码吧. 不知道你们用过NH或者EF没?我用过之后,一到数据库结构发生变化的时候我就觉得很繁琐,什么类型变化,还有映射关系得改,更可怕的是要是你的代码写得比较乱的,那就麻烦了. 现在这些问题统统都没有了,接下来得在这个ORMapping的基础上讲一下这个DB的migration 操作了,我这边基本已经完善好了,先把这个类图给大家看看,后面我会介绍每个类是干什么用的,怎么用. 有兴趣的朋

Stanford机器学习---第七讲. 机器学习系统设计

本文原始版本见http://blog.csdn.net/abcjennifer/article/details/7834256 本栏目(Machine learning)包括单参数的线性回归.多参数的线性回归.Octave Tutorial.Logistic Regression.Regularization.神经网络.机器学习系统设计.SVM(Support Vector Machines 支持向量机).聚类.降维.异常检测.大规模机器学习等章节.所有内容均来自Standford公开课mach

《上古天真论》第七讲文字版

上古天真论篇第七讲 主讲:徐文兵  主持:梁  冬 播出时间:2009-01-17  23:00—24:00 经文:四七,胫骨坚,发长极,身体盛壮,五七,阳明脉衰,面始焦,发始堕,六七,三阳脉衰于上,面皆焦,发始白,七七,任脉虚,太冲脉衰少,天癸竭,地道不通. 梁冬:是的,重新发现中医太美.重新发现<黄帝内经>的智慧.欢迎大家收听今天的国学堂,我是梁冬,而对面的仍然是厚朴中医学堂堂主徐文兵老师. 徐文兵:梁冬好!听众朋友们大家好! 梁冬:好,徐老师好!在上一周的时候呢我们讲到了这个女性的每七年

32位汇编第七讲,混合编程,内联汇编

32位汇编第七讲,混合编程 博客园IBinary原创 QQ:2510908331  博客连接:http://www.cnblogs.com/iBinary/ 转载请注明出处,谢谢 混合编程的概念,有时候我们会想,C语言可不可以调用汇编的函数,或者反过来调用 或者说C语言里面内部直接内联汇编去编写. 可以实现,静看怎么实现 一丶C语言调用汇编语言的函数 1.创建工程和代码 ①创建VC++控制台程序 FILE(文件) - NEW (新建) 然后我们打开源文件,一级一级展开,找到我们的main函数 那

《ArcGIS Engine+C#实例开发教程》第七讲 图层符号选择器的实现

原文:<ArcGIS Engine+C#实例开发教程>第七讲 图层符号选择器的实现 摘要:我们要实现的是图层符号选择器,与ArcMap中的Symbol Selector的类似.本讲较前几讲而言,些许有些复杂,不过只要仔细琢磨,认真操作,你就很容易实现如下所示的符号选择器.  教程目录: 第一讲 桌面GIS应用程序框架的建立 第二讲 菜单的添加及其实现 第三讲 MapControl与PageLayoutControl同步 第四讲 状态栏信息的添加与实现 第五讲 鹰眼的实现 第六讲 右键菜单添加与

Linux基础知识第七讲,用户权限以及用户操作命令

目录 Linux基础知识第七讲,用户权限以及用户操作命令 一丶简介linux用户,用户权限,组的概念. 1.1 基本概念 1.2 组 1.3 ls命令查看权限. 二丶用户权限修改命令 1.chmod 命令的使用 三丶超级用户,以及组操作. 1.什么是超级用户 2.组管理 四丶添加linux用户,以及删除linux用户 1.命令 2.用户命令 3.让添加的用户具有sudo权限 4.which 查看命令所执行位置的路径 5.用户切换 Linux基础知识第七讲,用户权限以及用户操作命令 一丶简介lin

【雅思基础课程】语法基础课程-第七讲

第七讲 定语和状语 \1. 定语 定语:"限定语",使表达形象具体. 中文常"前置",英文可"前置.后置". 定语较短常"前置",而较长常"后置". A. 前置定语 adj. (常描述细节或宣泄情感) n. (构成名词短语,常正式) pron. & 名词所有格 (可表时间或距离) eg: ? 机器吞了我的卡! ? The machine ate my card. ? 重读my表达自己内心的不满和愤怒

第七讲 stack

1. 栈(stack)这种数据结构在计算机中是相当出名的.栈中的数据是先进后出的(First In Last Out, FILO).栈只有一个出口,允许新增元素(只能在栈顶上增加).移出元素(只能移出栈顶元素).取得栈顶元素等操作.在STL中,栈是以别的容器作为底部结构,再将接口改变,使之符合栈的特性就可以了.因此实现非常的方便.下面就给出栈的函数列表和VS2008中栈的源代码,在STL中栈一共就5个常用操作函数(top().push().pop(). size().empty() ) 2. s