本文适合初学者,老鸟请点赞即走,谢谢。

文字功底有限,表述不恰当的地方,请各位多多包涵。

一,核心

现在ORM已经很多了,功能也齐全了,大家说我这是干无聊的事,造的连车轮子都还不算,反正我就当学习。

还有就是,下面这个不算正在的ORM,离真正在ORM差的很远的。

主要思想

二,实例测试

1,基础数据准备

1.1 数据库表结构(sqlite数据库)

       

    1.2 实体

      

    public class Msg
{
public string Id { get; set; }
public string Content { get; set; }
public string Name { get; set; }
public DateTime CreateTime { get; set; }
}

   2,开始插入数据

    2.1 创建了一个控制台程序做测试

        string connStr = string.Format("Data Source={0};", System.AppDomain.CurrentDomain.BaseDirectory + "App_Data\\db.db");
WangSql.ISqlExe sqlexe = new WangSql.SqlExe(WangSql.DbType.SQLLITE, connStr); string sql = "insert into Msg(Id,Content,Name,CreateTime) values(#Id#,#Content#,#Name#,#CreateTime#)";
Msg model = new Msg()
{
Id = Guid.NewGuid().ToString("N"),
Content = "这里是内容",
Name = "姓名",
CreateTime = DateTime.Now
};
sqlexe.NonQuery(sql, model);

    查看下数据呢,

    

    至此,测试成功,再来测试下呢。

    2.2 开8个线程,每个线程循环插入100条数据试试看。

    测试结果:好尴尬sqlite多线程容易锁库,以后操作这个库,还是队列吧,楼主本着不放弃不抛弃的精神,再来了一次。

    

    这次没被锁,数据库数据呢。

    

    数据也没少,OK,测试完成。

三,源码讲解(准确的是代码讲解)

  3.1 生成SQL

    大家有没有发现,我在执行时传入sql的格式

    insert into Msg(Id,Content,Name,CreateTime) values(#Id#,#Content#,#Name#,#CreateTime#)//有没有很熟悉呢,没错,就是借鉴(山寨)的ibatis的,哈哈

    就是这个样子的,

    表:Msg(Id,Content,Name,CreateTime)

    DbDataParameter:values(#Id#,#Content#,#Name#,#CreateTime#)

    DbDataParameter,这里支持值类型,string,object,object[],以及Hashtable和用户自定义类。

    下面就是生成SQL语句的代码、

        public string SqlInit(string sql, out List<string> paraName)
{
string sqlTag = sql;
List<string> sqlParaName = new List<string>();
Regex regex = new Regex("(#(.[^#]+?)#)");
var ms = regex.Matches(sql);
foreach (Match item in ms)
{
var p1 = item.Groups[];
var p2 = item.Groups[];
sqlTag = sqlTag.Replace(p1.Value, prefix + p2.Value);
if (!sqlParaName.Contains(p2.Value))
sqlParaName.Add(p2.Value);
}
paraName = sqlParaName;
return sqlTag;
}

    这个就会生成sql,并且还会把Parameter的key以集合的方式抛出去。

3.2 实体转成DbDataParameter

    当插入数据,参数传入的是个用户自定义类的话,需要做一次转换。先将实体转成Hashtable,然后再根据3.1生成sql抛出来的Parameter的key来生成Parameter集合。

    

        public static Hashtable ModelToHashtable(object model)
{
Hashtable ht = new Hashtable();
BindingFlags flag = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
PropertyInfo[] propertys = model.GetType().GetProperties(flag);
foreach (PropertyInfo pi in propertys)
{
string name = pi.Name;
if (!pi.CanRead) continue;
object value = pi.GetValue(model, null);
ht.Add(name, value);
}
return ht;
}

  3.3 完整NonQuery执行代码

        public int NonQuery(string sql, object para)
{
if (IsModel(para))//Model入参
{
Hashtable ht = DataMapHelper.ModelToHashtable(para);
List<string> paraName = new List<string>();
string sqlTag = SqlInit(sql, out paraName);
IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
for (int i = ; i < paraName.Count; i++)
{
string key = paraName[i];
object value = ht[key];
sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
}
var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
return result;
}
else if (para.GetType() == typeof(Hashtable))//Hashtanle入参
{
Hashtable ht = (Hashtable)para;
List<string> paraName = new List<string>();
string sqlTag = SqlInit(sql, out paraName);
IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
for (int i = ; i < paraName.Count; i++)
{
string key = paraName[i];
object value = ht[key];
sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
}
var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
return result;
}
else if (para.GetType() == typeof(object[]))
{
List<string> paraName = new List<string>();
string sqlTag = SqlInit(sql, out paraName);
object[] ht = (object[])para;
IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
for (int i = ; i < paraName.Count; i++)
{
string key = paraName[i];
object value = ht[i];
sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
}
var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
return result;
}
else//一个参数入参
{
List<string> paraName = new List<string>();
string sqlTag = SqlInit(sql, out paraName);
IDbDataParameter[] sqlParas = DBFactory.CreateDbDataParameters(type, paraName.Count);
for (int i = ; i < paraName.Count; i++)
{
string key = paraName[i];
object value = para;
sqlParas[i] = DBFactory.CreateDbDataParameter(type, prefix + key, value);
}
var result = helper.ExecuteNonQuery(sqlTag, sqlParas);
return result;
}
}

  3.4 查询语句

     如果是查询的话,执行完SQL返回一个DataTable,操作DataTable也太麻烦了吧,所以利用反射做了个实体转换器。

     DataTable转实体Model,DataRow转实体Model,DataTable转泛型T,DataRow转泛型T (之前的文章)

    

        public static T DataRowToModel<T>(DataRow row)
{
T model;
Type type = typeof(T);
ModelType modelType = GetModelType(type);
switch (modelType)
{
case ModelType.Struct://值类型
{
model = default(T);
if (row[] != null)
model = (T)row[];
}
break;
case ModelType.Enum://值类型
{
model = default(T);
if (row[] != null)
{
Type fiType = row[].GetType();
if (fiType == typeof(int))
{
model = (T)row[];
}
else if (fiType == typeof(string))
{
var value = Enum.Parse(typeof(T), row[].ToString());
if (value != null)
model = (T)value;
}
}
}
break;
case ModelType.String://引用类型 c#对string也当做值类型处理
{
model = default(T);
if (row[] != null)
model = (T)row[];
}
break;
case ModelType.Object://引用类型 直接返回第一行第一列的值
{
model = default(T);
if (row[] != null)
model = (T)row[];
}
break;
case ModelType.Else://引用类型
{
model = System.Activator.CreateInstance<T>();//引用类型 必须对泛型实例化
#region MyRegion
//获取model中的属性
BindingFlags flag = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
PropertyInfo[] modelPropertyInfos = type.GetProperties(flag);
//遍历model每一个属性并赋值DataRow对应的列
foreach (PropertyInfo pi in modelPropertyInfos)
{
if (!pi.CanWrite) continue;
//获取属性名称
string tempName = GetFieldName(pi);
String name = string.IsNullOrEmpty(tempName) ? pi.Name : tempName;
if (row.Table.Columns.Contains(name) && row[name] != null)
{
ModelType piType = GetModelType(pi.PropertyType);
switch (piType)
{
case ModelType.Struct:
{
var value = Convert.ChangeType(row[name], pi.PropertyType);
pi.SetValue(model, value, null);
}
break;
case ModelType.Enum:
{
Type fiType = row[name].GetType();
if (fiType == typeof(int))
{
pi.SetValue(model, row[name], null);
}
else if (fiType == typeof(string))
{
var value = Enum.Parse(typeof(T), row[name].ToString());
if (value != null)
pi.SetValue(model, (T)value, null);
}
}
break;
case ModelType.String:
{
var value = Convert.ChangeType(row[name], pi.PropertyType);
pi.SetValue(model, value, null);
}
break;
case ModelType.Object:
{
pi.SetValue(model, row[name], null);
}
break;
case ModelType.Else:
//throw new Exception("不支持该类型转换");
break;
default:
throw new Exception("未知类型");
}
}
}
#endregion
}
break;
default:
model = default(T);
break;
} return model;
}

好了,差不多了吧,还有些多谢没讲,可以看我另外两篇博客。

万能的SqlHelper,麻麻再也不用担心用什么数据库了

DataTable转实体Model,DataRow转实体Model,DataTable转泛型T,DataRow转泛型T

最后项目截图吧,稍后源码附上。

源码下载:

源码下载

最新文章

  1. SQLServer 事务隔离级别与锁的申请和释放
  2. C学习
  3. 【SSH三大框架】Hibernate基础第二篇:编写HibernateUtil工具类优化性能
  4. cocos2dx 3.1创建工 mac
  5. 存储过程修改产品描述页图片alt描述信息
  6. 使用开源word操作组件DocX的记录
  7. Traceroute原理介绍
  8. Yarn任务提交流程(源码分析)
  9. 了解JVM运行时的内存分配
  10. Educational Codeforces Round 54 [Rated for Div. 2] (CF1076)
  11. 了解fastadmin标准的控制器模块js的表格事件
  12. 探索未知种族之osg类生物---呼吸分解之更新循环二
  13. CF1137C Museums Tour
  14. 爬虫初窥day2:正则
  15. 自定义Metrics:让Prometheus监控你的应用程序
  16. EasyUI ---- draggable可拖动的用法
  17. struts2返回json字符串
  18. MyBatis For .NET学习-问题总结
  19. java.net.SocketException四大异常解决方案---转
  20. SSH原理记录

热门文章

  1. CoreData教程
  2. Spring:源码解读Spring IOC原理
  3. String驻留带来的危害
  4. Azure SQL Database (20) 使用SQL Server 2016 Upgrade Advisor
  5. 如何在 ASP.NET MVC 中集成 AngularJS(2)
  6. maven仓库信息分析站点推荐
  7. 如何用TDR来测试PCB板的线路阻抗
  8. PLSQL使用技巧
  9. 【转】C#语言之“string格式的日期时间字符串转为DateTime类型”的方法
  10. JSP生成Excel报表