说明

使用Expression(表达式目录树)转Entity的文章在园子里有很多,思路也大致也一样,我在前面有篇文章对解决思路有些说明,有兴趣的小伙伴可以看下 (传送门),刚接触表达式目录树时写的,不太严谨,但思路上应该不会有误导群众的嫌疑,具体实现代码还是以本篇的为准。

关于缓存和缺陷

实体查询,如:db.Query<Student>().Include(s => s.School).ToList();这种形式,因其SQL语句由代码拼接生成,所以比较固定,因此在这里对齐进行了缓存,既将表达式目录树生成的委托保存在一个字典中,第一次生成后,后面的操作就可以直接从字典中拿来用,其效率提升还是蛮明显的。这里因为我这个方法是之前写好的,在生成缓存key的时候使用 实体名+导航属性(多个导航属性,先按名称排序,然后拼接)的方式来生成,其实更普遍的做法是使用SQL语句作为缓存的key。

按需查询(Select),在这个代码里没有进行缓存,因为之前考虑到 Select(s => new {...}) 这种生成匿名类的查询,查询的字段不固定,那肯定就无法进行缓存,但是到最后也没能实现,下面的SqlDataReaderMapper.cs中有不少无用的代码,其实就是对生成匿名类对象和dynamic对象的尝试,然而,并没有成功。那么,在现阶段,这里的Func也还是可以缓存的,因为没有了匿名类的不确定性,所以生成的SQL语句时固定的,那生成的委托自然也就可以缓存了。只是在我的代码中没有实现,请自行解决吧。

不得不说无法支持 Select(s => new {})确实是个挺遗憾的地方,如果需要按需加载,必须定义一个实体承载查询结果,如 StudentDto 之类的,增加工作量不说,灵活性也欠缺了一些。

用于保存导航属性信息的工具类

  1. using System;
  2.  
  3. namespace MyOrm.Mappers
  4. {
  5. public class IncludePropertySdrMap
  6. {
  7. public Type Type { get; set; }
  8.  
  9. public string PropertyName { get; set; }
  10.  
  11. public int Index { get; set; }
  12. }
  13. }

用于实体查询的转换类

  1. using MyOrm.Reflections;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Data.SqlClient;
  5. using System.Linq;
  6. using System.Linq.Expressions;
  7.  
  8. namespace MyOrm.Mappers
  9. {
  10. public class SqlDataReaderConverter<T> where T : class, new()
  11. {
  12. private static readonly Dictionary<string, Func<SqlDataReader, T>> Dict
  13. = new Dictionary<string, Func<SqlDataReader, T>>();
  14.  
  15. public MyEntity Master { get; set; }
  16.  
  17. public List<string> Includes { get; set; }
  18.  
  19. public string Key { get; set; }
  20.  
  21. public SqlDataReaderConverter(string[] props = null)
  22. {
  23. Master = MyEntityContainer.Get(typeof(T));
  24.  
  25. if (props == null || props.Length == )
  26. {
  27. Includes = new List<string>();
  28. Key = typeof(T).Name;
  29. }
  30. else
  31. {
  32. Includes = props.ToList();
  33. Key = typeof(T).Name + "-" + string.Join("-", props.OrderBy(p => p).Distinct());
  34. }
  35. }
  36.  
  37. #region 反射
  38. public T ConvertToEntity(SqlDataReader sdr)
  39. {
  40. var entity = new T();
  41.  
  42. foreach (var property in Master.Properties)
  43. {
  44. property.PropertyInfo.SetValue(entity, sdr[property.Name]);
  45. }
  46.  
  47. foreach (var include in Includes)
  48. {
  49. var prop = Master.Properties.Single(p => p.Name == include);
  50. if (prop != null)
  51. {
  52. var subType = prop.PropertyInfo.PropertyType;
  53. var subEntityInfo = MyEntityContainer.Get(subType);
  54. var subEntity = Activator.CreateInstance(subType);
  55.  
  56. foreach (var subProperty in subEntityInfo.Properties)
  57. {
  58. if (subProperty.IsMap)
  59. {
  60. subProperty.PropertyInfo.SetValue(subEntity, sdr[$"{include}_{subProperty.Name}"]);
  61. }
  62. }
  63.  
  64. prop.PropertyInfo.SetValue(entity, subEntity);
  65. }
  66. }
  67.  
  68. return entity;
  69. }
  70. #endregion
  71.  
  72. #region 表达式目录树
  73. public Func<SqlDataReader, T> GetFunc(SqlDataReader sdr)
  74. {
  75. if (!Dict.TryGetValue(Key, out var func))
  76. {
  77. var sdrParameter = Expression.Parameter(typeof(SqlDataReader), "sdr");
  78. var memberBindings = new List<MemberBinding>();
  79. var subMemberMaps = new Dictionary<string, List<IncludePropertySdrMap>>();
  80. foreach (var include in Includes)
  81. {
  82. subMemberMaps.Add(include, new List<IncludePropertySdrMap>());
  83. }
  84.  
  85. for (var i = ; i < sdr.FieldCount; i++)
  86. {
  87. var fieldName = sdr.GetName(i);
  88. var fieldNames = fieldName.Split('_');
  89.  
  90. if (fieldNames.Length == )
  91. {
  92. var property = Master.Properties.Single(p => p.Name == fieldName);
  93. if (property != null)
  94. {
  95. var methodName = GetSdrMethodName(property.PropertyInfo.PropertyType);
  96. var methodCall = Expression.Call(sdrParameter,
  97. typeof(SqlDataReader).GetMethod(methodName) ?? throw new InvalidOperationException(),
  98. Expression.Constant(i));
  99.  
  100. Expression setValueExpression;
  101. if (property.PropertyInfo.PropertyType.IsGenericType &&
  102. property.PropertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
  103. {
  104. setValueExpression = Expression.Convert(methodCall, property.PropertyInfo.PropertyType);
  105. }
  106. else
  107. {
  108. setValueExpression = methodCall;
  109. }
  110.  
  111. //memberBindings.Add(Expression.Bind(property.PropertyInfo, methodCall));
  112. memberBindings.Add(
  113. Expression.Bind(
  114. property.PropertyInfo,
  115. Expression.Condition(
  116. Expression.TypeIs(
  117. Expression.Call(
  118. sdrParameter,
  119. typeof(SqlDataReader).GetMethod("get_Item", new[] {typeof(int)}) ??
  120. throw new InvalidOperationException(),
  121. Expression.Constant(i)),
  122. typeof(DBNull)
  123. ),
  124. Expression.Default(property.PropertyInfo.PropertyType),
  125. setValueExpression
  126. )
  127. )
  128. );
  129. }
  130. }
  131. else
  132. {
  133. if (subMemberMaps.TryGetValue(fieldNames[], out var list))
  134. {
  135. list.Add(new IncludePropertySdrMap { PropertyName = fieldNames[], Index = i });
  136. }
  137. }
  138. }
  139.  
  140. foreach (var include in subMemberMaps)
  141. {
  142. var prop = Master.Properties.Single(p => p.Name == include.Key);
  143. if (prop != null)
  144. {
  145. var subEntityInfo = MyEntityContainer.Get(prop.PropertyInfo.PropertyType);
  146. var subBindingList = new List<MemberBinding>();
  147. foreach (var subProperty in subEntityInfo.Properties)
  148. {
  149. if (subProperty.IsMap)
  150. {
  151. var mapper = include.Value.SingleOrDefault(v => v.PropertyName == subProperty.Name);
  152. if (mapper != null)
  153. {
  154. var methodName = GetSdrMethodName(subProperty.PropertyInfo.PropertyType);
  155. var methodCall = Expression.Call(
  156. sdrParameter,
  157. typeof(SqlDataReader).GetMethod(methodName) ??
  158. throw new InvalidOperationException(),
  159. Expression.Constant(mapper.Index));
  160.  
  161. Expression setValueExpression;
  162. if (subProperty.PropertyInfo.PropertyType.IsGenericType &&
  163. subProperty.PropertyInfo.PropertyType.GetGenericTypeDefinition() ==
  164. typeof(Nullable<>))
  165. {
  166. setValueExpression = Expression.Convert(methodCall,
  167. subProperty.PropertyInfo.PropertyType);
  168. }
  169. else
  170. {
  171. setValueExpression = methodCall;
  172. }
  173.  
  174. subBindingList.Add(
  175. Expression.Bind(
  176. subProperty.PropertyInfo,
  177. Expression.Condition(
  178. Expression.TypeIs(
  179. Expression.Call(
  180. sdrParameter,
  181. typeof(SqlDataReader).GetMethod("get_Item",
  182. new[] {typeof(int)}) ??
  183. throw new InvalidOperationException(),
  184. Expression.Constant(mapper.Index)),
  185. typeof(DBNull)
  186. ),
  187. Expression.Default(subProperty.PropertyInfo.PropertyType),
  188. setValueExpression
  189. )
  190. )
  191. );
  192. }
  193. }
  194.  
  195. var subInitExpression = Expression.MemberInit(
  196. Expression.New(prop.PropertyInfo.PropertyType),
  197. subBindingList);
  198. memberBindings.Add(Expression.Bind(prop.PropertyInfo, subInitExpression));
  199. }
  200. }
  201. }
  202.  
  203. var initExpression = Expression.MemberInit(Expression.New(typeof(T)), memberBindings);
  204. func = Expression.Lambda<Func<SqlDataReader, T>>(initExpression, sdrParameter).Compile();
  205. Dict.Add(Key, func);
  206. }
  207. else
  208. {
  209. //Console.WriteLine("应用了缓存");
  210. }
  211. return func;
  212. }
  213.  
  214. public T ConvertToEntity2(SqlDataReader sdr)
  215. {
  216. if (sdr.HasRows)
  217. {
  218. var func = GetFunc(sdr);
  219. if (sdr.Read())
  220. {
  221. return func.Invoke(sdr);
  222. }
  223. }
  224. return default(T);
  225. }
  226.  
  227. public List<T> ConvertToEntityList(SqlDataReader sdr)
  228. {
  229. var result = new List<T>();
  230. if (!sdr.HasRows)
  231. {
  232. return result;
  233. }
  234.  
  235. var func = GetFunc(sdr);
  236. do
  237. {
  238. while (sdr.Read())
  239. {
  240. result.Add(func(sdr));
  241. }
  242. } while (sdr.NextResult());
  243.  
  244. return result;
  245. }
  246.  
  247. public List<T> ConvertToEntityList2(SqlDataReader sdr)
  248. {
  249. var result = new List<T>();
  250. while (sdr.Read())
  251. {
  252. result.Add(ConvertToEntity2(sdr));
  253. }
  254. return result;
  255. }
  256.  
  257. /// <summary>
  258. /// 获取SqlDataReader转实体属性时调用的方法名
  259. /// </summary>
  260. /// <param name="type"></param>
  261. /// <returns></returns>
  262. private string GetSdrMethodName(Type type)
  263. {
  264. var realType = GetRealType(type);
  265. string methodName;
  266.  
  267. if (realType == typeof(string))
  268. {
  269. methodName = "GetString";
  270. }
  271. else if (realType == typeof(int))
  272. {
  273. methodName = "GetInt32";
  274. }
  275. else if (realType == typeof(DateTime))
  276. {
  277. methodName = "GetDateTime";
  278. }
  279. else if (realType == typeof(decimal))
  280. {
  281. methodName = "GetDecimal";
  282. }
  283. else if (realType == typeof(Guid))
  284. {
  285. methodName = "GetGuid";
  286. }
  287. else if (realType == typeof(bool))
  288. {
  289. methodName = "GetBoolean";
  290. }
  291. else
  292. {
  293. throw new ArgumentException($"不受支持的类型:{type.FullName}");
  294. }
  295.  
  296. return methodName;
  297. }
  298.  
  299. private static Type GetRealType(Type type)
  300. {
  301. var realType = type.IsGenericType &&
  302. type.GetGenericTypeDefinition() == typeof(Nullable<>)
  303. ? type.GetGenericArguments()[]
  304. : type;
  305.  
  306. return realType;
  307. }
  308. #endregion
  309. }
  310. }

用于按需查询的转换类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.SqlClient;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. using System.Reflection;
  7. using System.Text;
  8. using MyOrm.Expressions;
  9. using MyOrm.Reflections;
  10.  
  11. namespace MyOrm.Mappers
  12. {
  13. public class SqlDataReaderMapper
  14. {
  15. public Func<SqlDataReader, TTarget> ResolveClass<TTarget>(SqlDataReader sdr)
  16. {
  17. if (!sdr.HasRows) return null;
  18.  
  19. var sdrParameter = Expression.Parameter(typeof(SqlDataReader), "sdr");
  20. var memberBindings = new List<MemberBinding>();
  21. var subMemberMaps = new Dictionary<string, List<IncludePropertySdrMap>>();
  22.  
  23. var masterEntity = MyEntityContainer.Get(typeof(TTarget));
  24.  
  25. for (var i = ; i < sdr.FieldCount; i++)
  26. {
  27. var fieldName = sdr.GetName(i);
  28. var fieldNames = fieldName.Split("__");
  29.  
  30. if (fieldNames.Length == )
  31. {
  32. var property = masterEntity.Properties.Single(p => p.Name == fieldName);
  33. if (property != null)
  34. {
  35. var methodName = GetSdrMethodName(property.PropertyInfo.PropertyType);
  36. var methodCall = Expression.Call(sdrParameter,
  37. typeof(SqlDataReader).GetMethod(methodName) ?? throw new InvalidOperationException(),
  38. Expression.Constant(i));
  39.  
  40. Expression setValueExpression;
  41. if (property.PropertyInfo.PropertyType.IsGenericType &&
  42. property.PropertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
  43. {
  44. setValueExpression = Expression.Convert(methodCall, property.PropertyInfo.PropertyType);
  45. }
  46. else
  47. {
  48. setValueExpression = methodCall;
  49. }
  50.  
  51. //memberBindings.Add(Expression.Bind(property.PropertyInfo, methodCall));
  52. memberBindings.Add(
  53. Expression.Bind(
  54. property.PropertyInfo,
  55. Expression.Condition(
  56. Expression.TypeIs(
  57. Expression.Call(
  58. sdrParameter,
  59. typeof(SqlDataReader).GetMethod("get_Item", new[] { typeof(int) }) ??
  60. throw new InvalidOperationException(),
  61. Expression.Constant(i)),
  62. typeof(DBNull)
  63. ),
  64. Expression.Default(property.PropertyInfo.PropertyType),
  65. setValueExpression
  66. )
  67. )
  68. );
  69. }
  70. }
  71. else
  72. {
  73. if (subMemberMaps.TryGetValue(fieldNames[], out var list))
  74. {
  75. list.Add(new IncludePropertySdrMap { PropertyName = fieldNames[], Index = i });
  76. }
  77. }
  78. }
  79.  
  80. foreach (var include in subMemberMaps)
  81. {
  82. var prop = masterEntity.Properties.Single(p => p.Name == include.Key);
  83. if (prop != null)
  84. {
  85. var subEntityInfo = MyEntityContainer.Get(prop.PropertyInfo.PropertyType);
  86. var subBindingList = new List<MemberBinding>();
  87. foreach (var subProperty in subEntityInfo.Properties)
  88. {
  89. if (subProperty.IsMap)
  90. {
  91. var mapper = include.Value.SingleOrDefault(v => v.PropertyName == subProperty.Name);
  92. if (mapper != null)
  93. {
  94. var methodName = GetSdrMethodName(subProperty.PropertyInfo.PropertyType);
  95. var methodCall = Expression.Call(
  96. sdrParameter,
  97. typeof(SqlDataReader).GetMethod(methodName) ??
  98. throw new InvalidOperationException(),
  99. Expression.Constant(mapper.Index));
  100.  
  101. Expression setValueExpression;
  102. if (subProperty.PropertyInfo.PropertyType.IsGenericType &&
  103. subProperty.PropertyInfo.PropertyType.GetGenericTypeDefinition() ==
  104. typeof(Nullable<>))
  105. {
  106. setValueExpression = Expression.Convert(methodCall,
  107. subProperty.PropertyInfo.PropertyType);
  108. }
  109. else
  110. {
  111. setValueExpression = methodCall;
  112. }
  113.  
  114. subBindingList.Add(
  115. Expression.Bind(
  116. subProperty.PropertyInfo,
  117. Expression.Condition(
  118. Expression.TypeIs(
  119. Expression.Call(
  120. sdrParameter,
  121. typeof(SqlDataReader).GetMethod("get_Item",
  122. new[] { typeof(int) }) ??
  123. throw new InvalidOperationException(),
  124. Expression.Constant(mapper.Index)),
  125. typeof(DBNull)
  126. ),
  127. Expression.Default(subProperty.PropertyInfo.PropertyType),
  128. setValueExpression
  129. )
  130. )
  131. );
  132. }
  133. }
  134.  
  135. var subInitExpression = Expression.MemberInit(
  136. Expression.New(prop.PropertyInfo.PropertyType),
  137. subBindingList);
  138. memberBindings.Add(Expression.Bind(prop.PropertyInfo, subInitExpression));
  139. }
  140. }
  141. }
  142.  
  143. var initExpression = Expression.MemberInit(Expression.New(typeof(TTarget)), memberBindings);
  144. return Expression.Lambda<Func<SqlDataReader, TTarget>>(initExpression, sdrParameter).Compile();
  145. }
  146.  
  147. public Func<SqlDataReader, TTarget> ResolveConstant<TTarget>(SqlDataReader sdr, string fieldName = "")
  148. {
  149. var type = typeof(TTarget);
  150. var sdrParameter = Expression.Parameter(typeof(SqlDataReader), "sdr");
  151. MethodCallExpression callExpression;
  152. if (string.IsNullOrWhiteSpace(fieldName))
  153. {
  154. var methodName = GetSdrMethodName(type);
  155. callExpression = Expression.Call(sdrParameter, typeof(SqlDataReader).GetMethod(methodName),
  156. Expression.Constant());
  157. return Expression.Lambda<Func<SqlDataReader, TTarget>>(callExpression, sdrParameter).Compile();
  158. }
  159. else
  160. {
  161. callExpression = Expression.Call(sdrParameter,
  162. typeof(SqlDataReader).GetMethod("get_item", new[] {typeof(string)}),
  163. Expression.Constant(fieldName));
  164. var convertExpression = Expression.Convert(callExpression, type);
  165. return Expression.Lambda<Func<SqlDataReader, TTarget>>(convertExpression, sdrParameter).Compile();
  166. }
  167. }
  168.  
  169. public Func<SqlDataReader, dynamic> Resolve2(SqlDataReader sdr)
  170. {
  171. var sdrParameter = Expression.Parameter(typeof(SqlDataReader), "sdr");
  172. var newExpression = Expression.New(typeof(System.Dynamic.ExpandoObject));
  173. var convertExpression = Expression.Convert(newExpression, typeof(IDictionary<string, object>));
  174.  
  175. var memberBindings = new List<MemberBinding>();
  176. for(var i = ; i < sdr.FieldCount; i++)
  177. {
  178. var nameExpression = Expression.Call(sdrParameter, typeof(SqlDataReader).GetMethod("GetName"), Expression.Constant(i));
  179. //var itemExpression = Expression.Call(
  180. // sdrParameter,
  181. // typeof(SqlDataReader).GetMethod("get_Item",
  182. // new[] { typeof(int) }) ??
  183. // throw new InvalidOperationException(),
  184. // Expression.Constant(i));
  185. //var type = Expression.Constant(Expression.Call(sdrParameter, typeof(SqlDataReader).GetMethod("GetFieldType", new[] { typeof(int) }), Expression.Constant(i)));
  186. var valueExpression = Expression.Call(sdrParameter, typeof(SqlDataReader).GetMethod("GetValue", new[] { typeof(int) }), Expression.Constant(i));
  187.  
  188. //var callExpression = Expression.Call(
  189. // convertExpression,
  190. // typeof(IDictionary<string, object>).GetMethod("Add"),
  191. // nameExpression, valueExpression);
  192.  
  193. Expression.Call(newExpression,
  194. typeof(System.Dynamic.ExpandoObject).GetMethod("TryAdd", new[] { typeof(string), typeof(object) }),
  195. nameExpression,
  196. valueExpression);
  197. }
  198. var initExpression = Expression.MemberInit(newExpression);
  199. var lambda = Expression.Lambda<Func<SqlDataReader, dynamic>>(initExpression, sdrParameter);
  200. return lambda.Compile();
  201. }
  202.  
  203. public List<T> ConvertToList<T>(SqlDataReader sdr)
  204. {
  205. var result = new List<T>();
  206. if (!sdr.HasRows)
  207. {
  208. return result;
  209. }
  210.  
  211. var func = typeof(T).IsClass && typeof(T) != typeof(string) ? ResolveClass<T>(sdr) : ResolveConstant<T>(sdr);
  212.  
  213. if (func == null)
  214. {
  215. return result;
  216. }
  217.  
  218. while (sdr.Read())
  219. {
  220. result.Add(func.Invoke(sdr));
  221. }
  222.  
  223. return result;
  224. }
  225.  
  226. public T ConvertToEntity<T>(SqlDataReader sdr)
  227. {
  228. if (!sdr.HasRows)
  229. {
  230. return default(T);
  231. }
  232.  
  233. var func = typeof(T).IsClass ? ResolveClass<T>(sdr) : ResolveConstant<T>(sdr);
  234.  
  235. if (func == null)
  236. {
  237. return default(T);
  238. }
  239.  
  240. if (sdr.Read())
  241. {
  242. return func.Invoke(sdr);
  243. }
  244.  
  245. return default(T);
  246. }
  247.  
  248. public List<dynamic> ConvertToList(SqlDataReader sdr)
  249. {
  250. var result = new List<dynamic>();
  251. if (!sdr.HasRows)
  252. {
  253. return result;
  254. }
  255.  
  256. var func = Resolve2(sdr);
  257.  
  258. if (func == null)
  259. {
  260. return result;
  261. }
  262.  
  263. while (sdr.Read())
  264. {
  265. result.Add(func.Invoke(sdr));
  266. }
  267.  
  268. return result;
  269. }
  270.  
  271. public dynamic ConvertToEntity(SqlDataReader sdr)
  272. {
  273. if (!sdr.HasRows)
  274. {
  275. return null;
  276. }
  277.  
  278. var func = Resolve2(sdr);
  279.  
  280. if (func != null && sdr.Read())
  281. {
  282. return func.Invoke(sdr);
  283. }
  284.  
  285. return null;
  286. }
  287.  
  288. private string GetSdrMethodName(Type type)
  289. {
  290. var realType = GetRealType(type);
  291. string methodName;
  292.  
  293. if (realType == typeof(string))
  294. {
  295. methodName = "GetString";
  296. }
  297. else if (realType == typeof(int))
  298. {
  299. methodName = "GetInt32";
  300. }
  301. else if (realType == typeof(DateTime))
  302. {
  303. methodName = "GetDateTime";
  304. }
  305. else if (realType == typeof(decimal))
  306. {
  307. methodName = "GetDecimal";
  308. }
  309. else if (realType == typeof(Guid))
  310. {
  311. methodName = "GetGuid";
  312. }
  313. else if (realType == typeof(bool))
  314. {
  315. methodName = "GetBoolean";
  316. }
  317. else
  318. {
  319. throw new ArgumentException($"不受支持的类型:{type.FullName}");
  320. }
  321.  
  322. return methodName;
  323. }
  324.  
  325. public Type ConvertSdrFieldToType(SqlDataReader sdr)
  326. {
  327. return null;
  328. }
  329.  
  330. private static Type GetRealType(Type type)
  331. {
  332. var realType = type.IsGenericType &&
  333. type.GetGenericTypeDefinition() == typeof(Nullable<>)
  334. ? type.GetGenericArguments()[]
  335. : type;
  336.  
  337. return realType;
  338. }
  339. }
  340. }

【手撸一个ORM】第七步、SqlDataReader转实体的更多相关文章

  1. 【手撸一个ORM】第一步、实体约定和描述

    一.约定 数据实体必须实现 IEntity 接口,该接口定义了一个int类型的Id属性,既每个实体必须有一个名称为Id的自增主键. 若数据表的主键列名称不是Id,可以通过 [MyKey("主 ...

  2. 【手撸一个ORM】第九步、orm默认配置类 MyDbConfiguration,一次配置,简化实例化流程

    这个实现比较简单,事实上可配置的项目很多,如有需要,请读者自行扩展 using System; namespace MyOrm { public class MyDbConfiguration { p ...

  3. 【手撸一个ORM】MyOrm的使用说明

    [手撸一个ORM]第一步.约定和实体描述 [手撸一个ORM]第二步.封装实体描述和实体属性描述 [手撸一个ORM]第三步.SQL语句构造器和SqlParameter封装 [手撸一个ORM]第四步.Ex ...

  4. 【手撸一个ORM】第六步、对象表达式解析和Select表达式解析

    说明 一个Orm自然不仅仅包含条件表达式,还会有如下的场景: OrderBy(s => s.StudentName) Select<StudentDto>(s => new S ...

  5. 【手撸一个ORM】第四步、Expression(表达式目录树)扩展

    到这里,Orm的基架已经搭起来了,接下来就是激动人心的部分,表达式目录树转Sql语句,SqlDataReader转数据实体等等,但是在这之前,我们需要扩展下表达式目录树的方法,以方便后面的相关操作. ...

  6. 【手撸一个ORM】第十步、数据操作工具类 MyDb

    说明 其实就是数据库操作的一些封装,很久不用SqlCommand操作数据库了,看了点园子里的文章就直接上手写了,功能上没问题,但写法上是否完美高效无法保证,建议有需要的朋友自己重写,当然如果能把最佳实 ...

  7. 【手撸一个ORM】第三步、SQL语句构造器和SqlParameter封装

    既然是数据库工具,自然少不了增删改查的sql语句,在这里将这些常用SQL拼接操作集成到 [SqlServerBuilder.cs] 当中,方便后面调用. 近几年在项目中一直使用Dapper操作数据库, ...

  8. 【手撸一个ORM】第五步、Expression(表达式目录树)转换为Where子句

    说明 在SQL中,查询.修改比较常用到WHERE子句,在这里根据使用场景不同,定义了两个类,一个用于查询,一个用于修改(插入)操作.原因是: 查询操作支持一级导航属性查询,如student.Schoo ...

  9. 【手撸一个ORM】第八步、查询工具类

    一.实体查询 using MyOrm.Commons; using MyOrm.DbParameters; using MyOrm.Expressions; using MyOrm.Mappers; ...

随机推荐

  1. 找工作--volatile

    在Java编写的程序中,有时为了提高程序的运行效率,编译器会自动对其进行优化,把经常访问的变量缓存起来,程序在读取这个变量时有可能会直接从缓存(例如寄存器)中来读取这个值,而不会从内存中读取.这样做的 ...

  2. ssh配置免登 Ubuntu环境

    配置之前,可能需要修改下每台机器的hostname,修改方法 1.直接修改hostname文件:sudo vi /etc/hostname 2.重启服务器:shutdown -r now Ubuntu ...

  3. RS485总线防雷保护方案

    RS485作为最为最常用的电表通讯方式之一.日常生活中雷电和静电干扰已经成为485通信总线在实际工程经常遇到的问题.故如何对芯片以及总线进行有效的保护,是摆在每一个使用者面前的一个问题.在这里,我们主 ...

  4. C#使用Command将dataGrideView表格内数据与数据库交互

    本文主要介绍通过Command类使用SQL插入指令insert与查询指令select将dataGrideView表格内添加至数据库,与从数据库读出数据存放在dataGrideView表格中. C#制作 ...

  5. springMVC绑定json参数之二(2.2.2)

    二.springmvc 接收不同格式的json字符串 2).格式二:json字符串数组 前台: test = function () { var test = ["123",&qu ...

  6. cadence spb 16.5 破解过程实例和使用感受_赤松子耶_新浪博客

    cadence spb 16.5 破解过程实例和使用感受_赤松子耶_新浪博客 Cadence Allegro16.5详细安装具体的步骤 1.下载SPB16.5下来后,点setup.exe,先安装第一项 ...

  7. 02_android下单元测试

    Java的单元测试JUnit. Java程序入口是main方法.一般不在安卓程序入口 @Override protected void onCreate(Bundle savedInstanceSta ...

  8. [51nod1270] 数组的最大代价(简单dp)

    解题关键:先由贪心的思想得出任何一个位置只能取1或者a[i],然后dp即可. #include<bits/stdc++.h> using namespace std; typedef lo ...

  9. centos MAC 地址与报错eth0 unknown interface no such device

    eth0 unknown interface no such device 出现这个原因是由于虚拟机直接COPY过来,MAC地址发生了变化,但eth0 里仍然记录着旧的MAC地址. 解决方法: vim ...

  10. 2、linux-compress and uncompresse

    1.单个文件 压缩 解压 gzip file1  gzip -d file1.gz或者gunzip file1.gz #file1文件即会被压缩为 file1.gz,file1原文件删除:解压后同样删 ...