DbSqlHelper.cs 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Common;
  5. using System.Diagnostics;
  6. using System.Linq;
  7. using System.Reflection;
  8. using System.Text;
  9. namespace LJLib.DAL.SQL
  10. {
  11. /// <summary>
  12. /// 全局初始化时,需要添加要支持的引擎(SqlServer/Sqlite)
  13. /// </summary>
  14. internal static class DbSqlHelper
  15. {
  16. /// <summary>
  17. /// 从数据库获取当前时间
  18. /// SQL Server :SELECT GETDATE()
  19. /// SQLite :SELECT DATETIME()
  20. /// </summary>
  21. public static DateTime GetServerTime<TCommand>(TCommand cmd) where TCommand : DbCommand
  22. {
  23. var engine = GetEngine(cmd.GetType());
  24. return engine.GetServerTime(cmd);
  25. }
  26. /// <summary>
  27. /// 获取单表中符合条件的行数
  28. /// </summary>
  29. public static int SelectCount<TCommand>(TCommand cmd, string table, string wherestr, IDictionary<string, object> sqlparams = null) where TCommand : DbCommand
  30. {
  31. string strcmd = "SELECT COUNT(0) FROM " + table;
  32. if (!string.IsNullOrEmpty(wherestr))
  33. {
  34. wherestr = wherestr.Trim();
  35. strcmd += " WHERE " + wherestr;
  36. }
  37. cmd.CommandText = strcmd;
  38. cmd.CommandType = CommandType.Text;
  39. cmd.Parameters.Clear();
  40. if (sqlparams != null)
  41. {
  42. foreach (var sqlparam in sqlparams)
  43. {
  44. var value = sqlparam.Value;
  45. if (value == null)
  46. {
  47. value = DBNull.Value;
  48. }
  49. AddWithValue(cmd, sqlparam.Key, value);
  50. }
  51. }
  52. return Convert.ToInt32(cmd.ExecuteScalar());
  53. }
  54. /// <summary>
  55. /// 添加参数值
  56. /// </summary>
  57. private static void AddWithValue<TCommand>(TCommand cmd, string name, object value) where TCommand : DbCommand
  58. {
  59. var engine = GetEngine(cmd.GetType());
  60. engine.AddWithValue(cmd, name, value);
  61. if (cmd.Parameters[name].Value == null)
  62. {
  63. cmd.Parameters[name].Value = DBNull.Value;
  64. }
  65. }
  66. public static void SelectJoin<TCommand, T>(TCommand cmd, string selectStr, string whereStr, IDictionary<string, object> parms, string orderByStr, string outputFields, int pageindex, int pagesize, List<T> returnList)
  67. where TCommand : DbCommand
  68. where T : new()
  69. {
  70. cmd.CommandText = SqlStrHelper.BuildSelectStr(selectStr, ref outputFields, whereStr, orderByStr, pageindex, pagesize); ;
  71. cmd.CommandType = CommandType.Text;
  72. cmd.Parameters.Clear();
  73. if (parms != null)
  74. {
  75. foreach (var parm in parms)
  76. {
  77. AddWithValue(cmd, parm.Key, parm.Value);
  78. }
  79. }
  80. var properties = GetProperties(typeof(T), outputFields);
  81. GetValues(cmd, returnList, properties);
  82. }
  83. public static void SelectJoin<TCommand, T>(TCommand cmd, string selectStr, string whereStr, IDictionary<string, object> parms, string orderByStr, string outputFields, int pageindex, int pagesize, List<T> returnList, ref int totalcnt)
  84. where TCommand : DbCommand
  85. where T : new()
  86. {
  87. var parseResult = SqlStrHelper.ParseSelectStr(selectStr);
  88. if (parseResult.selectStr.ToUpper().Contains("DISTINCT"))
  89. {
  90. throw new NotImplementedException("不要过分依赖DISTINCT");
  91. }
  92. cmd.CommandText = SqlStrHelper.BuildSelectStr(parseResult, outputFields, whereStr, orderByStr, pageindex, pagesize);
  93. cmd.CommandType = CommandType.Text;
  94. cmd.Parameters.Clear();
  95. if (parms != null)
  96. {
  97. foreach (var parm in parms)
  98. {
  99. AddWithValue(cmd, parm.Key, parm.Value);
  100. }
  101. }
  102. var properties = GetProperties(typeof(T), outputFields);
  103. GetValues(cmd, returnList, properties);
  104. string strcmd = parseResult.selectStr + " COUNT(0) " + parseResult.fromStr;
  105. if (!string.IsNullOrEmpty(whereStr))
  106. {
  107. whereStr = whereStr.Trim();
  108. strcmd += " WHERE " + whereStr;
  109. }
  110. cmd.CommandText = strcmd;
  111. //cmd.CommandType = CommandType.Text;
  112. //cmd.Parameters.Clear();
  113. try
  114. {
  115. totalcnt = Convert.ToInt32(cmd.ExecuteScalar());
  116. }
  117. catch (Exception ex)
  118. {
  119. throw new Exception(string.Format("ex:{0}\r\ncmd:{1}", ex, cmd.CommandText));
  120. }
  121. }
  122. private static object ConvertValue(Type parmType, object value)
  123. {
  124. if (!parmType.IsAssignableFrom(value.GetType()))
  125. {
  126. if (parmType.IsAssignableFrom(typeof(byte)))
  127. {
  128. value = Convert.ToByte(value);
  129. }
  130. else if (parmType.IsAssignableFrom(typeof(sbyte)))
  131. {
  132. value = Convert.ToSByte(value);
  133. }
  134. else if (parmType.IsAssignableFrom(typeof(short)))
  135. {
  136. value = Convert.ToInt16(value);
  137. }
  138. else if (parmType.IsAssignableFrom(typeof(ushort)))
  139. {
  140. value = Convert.ToUInt16(value);
  141. }
  142. else if (parmType.IsAssignableFrom(typeof(int)))
  143. {
  144. value = Convert.ToInt32(value);
  145. }
  146. else if (parmType.IsAssignableFrom(typeof(uint)))
  147. {
  148. value = Convert.ToUInt32(value);
  149. }
  150. else if (parmType.IsAssignableFrom(typeof(long)))
  151. {
  152. value = Convert.ToInt64(value);
  153. }
  154. else if (parmType.IsAssignableFrom(typeof(ulong)))
  155. {
  156. value = Convert.ToUInt64(value);
  157. }
  158. else if (parmType.IsAssignableFrom(typeof(float)))
  159. {
  160. value = Convert.ToSingle(value);
  161. }
  162. else if (parmType.IsAssignableFrom(typeof(double)))
  163. {
  164. value = Convert.ToDouble(value);
  165. }
  166. else if (parmType.IsAssignableFrom(typeof(decimal)))
  167. {
  168. value = Convert.ToDecimal(value);
  169. }
  170. else if (parmType.IsAssignableFrom(typeof(bool)))
  171. {
  172. value = Convert.ToBoolean(value);
  173. }
  174. else if (parmType.IsAssignableFrom(typeof(bool)))
  175. {
  176. value = Convert.ToBoolean(value);
  177. }
  178. else if (parmType.IsAssignableFrom(typeof(char)))
  179. {
  180. value = Convert.ToChar(value);
  181. }
  182. else if (parmType.IsAssignableFrom(typeof(DateTime)))
  183. {
  184. value = Convert.ToDateTime(value);
  185. }
  186. else if (parmType.IsAssignableFrom(typeof(string)))
  187. {
  188. value = Convert.ToString(value);
  189. }
  190. else if (parmType.IsEnum)
  191. {
  192. value = Enum.ToObject(parmType, value);
  193. }
  194. else
  195. {
  196. throw new Exception(string.Format("不能将{0}转换成{1}", value.GetType(), parmType));
  197. }
  198. }
  199. return value;
  200. }
  201. public static int Select<TCommand, T>(TCommand cmd, string tablename, string whereStr, IDictionary<string, object> parms, string orderStr, int pagesize, int pageindex, IList<T> modles, IDictionary<string, string> maps, string fields)
  202. where TCommand : DbCommand
  203. where T : new()
  204. {
  205. var strCmd = string.Format("SELECT {0} FROM {1}", fields, tablename);
  206. cmd.CommandText = SqlStrHelper.BuildSelectStr(strCmd, ref fields, whereStr, orderStr, pageindex, pagesize);
  207. cmd.CommandType = CommandType.Text;
  208. cmd.Parameters.Clear();
  209. if (parms != null)
  210. {
  211. foreach (var parm in parms)
  212. {
  213. AddWithValue(cmd, parm.Key, parm.Value);
  214. }
  215. }
  216. var targetMaps = GetTargetMaps<T>(maps, fields);
  217. using (var reader = cmd.ExecuteReader())
  218. {
  219. while (reader.Read())
  220. {
  221. T modle = new T();
  222. GetValue(reader, modle, targetMaps);
  223. modles.Add(modle);
  224. }
  225. }
  226. return modles.Count;
  227. }
  228. private static void GetValue(DbDataReader reader, object modle, Dictionary<string, PropertyInfo> targetMaps)
  229. {
  230. foreach (var property in targetMaps)
  231. {
  232. MethodInfo setMethod = property.Value.GetSetMethod();
  233. if (setMethod == null)
  234. {
  235. continue;
  236. }
  237. object value = null;
  238. try
  239. {
  240. value = reader[property.Key];
  241. }
  242. catch (Exception)
  243. {
  244. continue;
  245. }
  246. if (value == null || value == DBNull.Value)
  247. {
  248. continue;
  249. }
  250. if (value is string)
  251. {
  252. value = value.ToString().Trim();
  253. }
  254. var parmType = setMethod.GetParameters()[0].ParameterType;
  255. value = ConvertValue(parmType, value);
  256. setMethod.Invoke(modle, new object[] { value });
  257. }
  258. }
  259. public static int Select<TCommand, T>(TCommand cmd, IList<T> modles, string wherestr, string fields = "*")
  260. where TCommand : DbCommand
  261. where T : new()
  262. {
  263. return Select(cmd, modles, wherestr, null, null, fields, 0, 0);
  264. }
  265. public static int Select<TCommand, T>(TCommand cmd, IList<T> modles, string wherestr, IDictionary<string, object> sqlparams, string fields = "*")
  266. where TCommand : DbCommand
  267. where T : new()
  268. {
  269. return Select(cmd, modles, wherestr, sqlparams, null, fields, 0, 0);
  270. }
  271. public static int Select<TCommand, T>(TCommand cmd, IList<T> modles, string wherestr, IDictionary<string, object> sqlparams, int pageindex, int pagesize, string orderstr, string fields = "*")
  272. where TCommand : DbCommand
  273. where T : new()
  274. {
  275. return Select(cmd, modles, wherestr, sqlparams, orderstr, fields, pageindex, pagesize);
  276. }
  277. public static int Select<TCommand, T>(TCommand cmd, IList<T> modles, string whereStr, IDictionary<string, object> sqlparams, string orderByStr, string outputFields, int pageindex, int pagesize)
  278. where TCommand : DbCommand
  279. where T : new()
  280. {
  281. if (modles.IsReadOnly)
  282. {
  283. throw new ArgumentException("参数modles不能为只读");
  284. }
  285. var propertyies = GetProperties(typeof(T), outputFields);
  286. if (propertyies.Count == 0)
  287. {
  288. propertyies = new List<PropertyInfo>(GetProperties(typeof(T)).Values);
  289. }
  290. var strCmd = string.Empty;
  291. foreach (var propertyInfo in propertyies)
  292. {
  293. if (string.IsNullOrEmpty(strCmd))
  294. {
  295. strCmd = propertyInfo.Name;
  296. }
  297. else
  298. {
  299. strCmd += "," + propertyInfo.Name;
  300. }
  301. }
  302. strCmd = "SELECT " + strCmd + " FROM " + typeof(T).Name;
  303. var outCmdStr = SqlStrHelper.BuildSelectStr(strCmd, ref outputFields, whereStr, orderByStr, pageindex, pagesize);
  304. cmd.CommandText = outCmdStr;
  305. cmd.CommandType = CommandType.Text;
  306. cmd.Parameters.Clear();
  307. if (sqlparams != null)
  308. {
  309. foreach (var parm in sqlparams)
  310. {
  311. AddWithValue(cmd, parm.Key, parm.Value);
  312. }
  313. }
  314. GetValues(cmd, modles, propertyies);
  315. return modles.Count;
  316. }
  317. private static void GetValues<TCommand, T>(TCommand cmd, IList<T> modles, IList<PropertyInfo> propertyies)
  318. where TCommand : DbCommand
  319. where T : new()
  320. {
  321. try
  322. {
  323. using (var reader = cmd.ExecuteReader())
  324. {
  325. while (reader.Read())
  326. {
  327. T modle = new T();
  328. GetValue(reader, modle, propertyies);
  329. modles.Add(modle);
  330. }
  331. }
  332. }
  333. catch (Exception)
  334. {
  335. //Debug.Write(cmd.CommandText);
  336. throw;
  337. }
  338. }
  339. private static void GetValue<T>(DbDataReader reader, T modle, IList<PropertyInfo> propertyies)
  340. {
  341. foreach (PropertyInfo property in propertyies)
  342. {
  343. MethodInfo setMethod = property.GetSetMethod();
  344. if (setMethod == null)
  345. {
  346. continue;
  347. }
  348. object value = null;
  349. try
  350. {
  351. value = reader[property.Name];
  352. }
  353. catch (Exception)
  354. {
  355. continue;
  356. }
  357. if (value == null || value == DBNull.Value)
  358. {
  359. continue;
  360. }
  361. if (value is string)
  362. {
  363. value = value.ToString().Trim();
  364. }
  365. var parmType = setMethod.GetParameters()[0].ParameterType;
  366. value = ConvertValue(parmType, value);
  367. setMethod.Invoke(modle, new object[] { value });
  368. }
  369. }
  370. private static object _pksyncRoot = new object();
  371. private static Dictionary<Type, string[]> _type_pks = new Dictionary<Type, string[]>();
  372. private static string[] GetPKs(Type type)
  373. {
  374. // DONE: 返回模型类的主键
  375. lock (_pksyncRoot)
  376. {
  377. if (_type_pks.ContainsKey(type))
  378. {
  379. return _type_pks[type];
  380. }
  381. var attrs = type.GetCustomAttributes(typeof(PK), true);
  382. if (attrs.Length == 0)
  383. {
  384. _type_pks[type] = new string[] { };
  385. }
  386. else
  387. {
  388. PK pk = attrs[0] as PK;
  389. _type_pks[type] = pk.keys;
  390. }
  391. return _type_pks[type];
  392. }
  393. }
  394. public static int SelectOne<TCommand, T>(TCommand cmd, string tablename, string whereStr, IDictionary<string, object> parms, T Modle, string fields) where TCommand : DbCommand
  395. {
  396. // 生成语句
  397. var propertyies = GetProperties(typeof(T), fields);
  398. if (propertyies.Count == 0)
  399. {
  400. propertyies = new List<PropertyInfo>(GetProperties(typeof(T)).Values);
  401. }
  402. var strCmd = string.Empty;
  403. foreach (var propertyInfo in propertyies)
  404. {
  405. if (string.IsNullOrEmpty(strCmd))
  406. {
  407. strCmd = propertyInfo.Name;
  408. }
  409. else
  410. {
  411. strCmd += "," + propertyInfo.Name;
  412. }
  413. }
  414. strCmd = "SELECT " + strCmd + " FROM " + tablename;
  415. if (!string.IsNullOrEmpty(whereStr))
  416. {
  417. strCmd += " WHERE " + whereStr;
  418. }
  419. cmd.CommandText = strCmd;
  420. cmd.CommandType = CommandType.Text;
  421. cmd.Parameters.Clear();
  422. if (parms != null)
  423. {
  424. foreach (var kvp in parms)
  425. {
  426. AddWithValue(cmd, kvp.Key, kvp.Value);
  427. }
  428. }
  429. using (var reader = cmd.ExecuteReader())
  430. {
  431. if (!reader.Read())
  432. {
  433. return 0;
  434. }
  435. GetValue(reader, Modle, propertyies);
  436. return 1;
  437. }
  438. }
  439. public static int SelectOne<TCommand, T>(TCommand cmd, T modle, string fields = "*") where TCommand : DbCommand
  440. {
  441. // 查找非空主键
  442. var fpkpropertyies = GetNotNullProperties(modle);
  443. // 生成语句
  444. var propertyies = GetProperties(typeof(T), fields);
  445. if (propertyies.Count == 0)
  446. {
  447. propertyies = new List<PropertyInfo>(GetProperties(typeof(T)).Values);
  448. }
  449. var strCmd = string.Empty;
  450. foreach (var propertyInfo in propertyies)
  451. {
  452. if (string.IsNullOrEmpty(strCmd))
  453. {
  454. strCmd = propertyInfo.Name;
  455. }
  456. else
  457. {
  458. strCmd += "," + propertyInfo.Name;
  459. }
  460. }
  461. strCmd = "SELECT " + strCmd + " FROM " + typeof(T).Name;
  462. strCmd += string.Format(" WHERE {0}=@{0}", fpkpropertyies[0].Name);
  463. for (int i = 1; i < fpkpropertyies.Count; i++)
  464. {
  465. strCmd += string.Format(" AND {0}=@{0}", fpkpropertyies[i].Name);
  466. }
  467. cmd.CommandText = strCmd;
  468. cmd.CommandType = CommandType.Text;
  469. cmd.Parameters.Clear();
  470. foreach (var property in fpkpropertyies)
  471. {
  472. object value = property.GetGetMethod().Invoke(modle, null);
  473. AddWithValue(cmd, "@" + property.Name, value);
  474. }
  475. using (var reader = cmd.ExecuteReader())
  476. {
  477. if (!reader.Read())
  478. {
  479. return 0;
  480. }
  481. GetValue(reader, modle, propertyies);
  482. return 1;
  483. }
  484. }
  485. /// <summary>
  486. /// 查找非空主键
  487. /// </summary>
  488. /// <typeparam name="T"></typeparam>
  489. /// <param name="modle"></param>
  490. /// <returns></returns>
  491. private static IList<PropertyInfo> GetNotNullProperties<T>(T modle)
  492. {
  493. var pks = GetPKs(typeof(T));
  494. if (pks == null || pks.Length == 0)
  495. {
  496. throw new Exception(string.Format("模型类{0}没有定义主键", typeof(T).FullName));
  497. }
  498. IList<PropertyInfo> fpkpropertyies = null;
  499. foreach (var pk in pks)
  500. {
  501. if (string.IsNullOrEmpty(pk))
  502. {
  503. throw new Exception(string.Format("模型类{0}的主键不能为空", typeof(T).FullName));
  504. }
  505. var withnullpk = false;
  506. var pkproperties = GetProperties(typeof(T), pk);
  507. if (pkproperties.Count == 0)
  508. {
  509. throw new Exception(string.Format("模型类{0}的主键与字段名不符", typeof(T).FullName));
  510. }
  511. foreach (var propertyInfo in pkproperties)
  512. {
  513. var getMethod = propertyInfo.GetGetMethod();
  514. var value = getMethod.Invoke(modle, null);
  515. if (value == null)
  516. {
  517. withnullpk = true;
  518. break;
  519. }
  520. }
  521. if (!withnullpk)
  522. {
  523. fpkpropertyies = pkproperties;
  524. break;
  525. }
  526. }
  527. if (fpkpropertyies == null)
  528. {
  529. throw new Exception("转入模型主键为空");
  530. }
  531. return fpkpropertyies;
  532. }
  533. public static int Delete<TCommand, T>(TCommand cmd, T modle) where TCommand : DbCommand
  534. {
  535. var fpkpropertyies = GetNotNullProperties(modle);
  536. var strCmd = string.Empty;
  537. strCmd = "DELETE FROM " + typeof(T).Name;
  538. strCmd += string.Format(" WHERE {0}=@{0}", fpkpropertyies[0].Name);
  539. for (int i = 1; i < fpkpropertyies.Count; i++)
  540. {
  541. strCmd += string.Format(" AND {0}=@{0}", fpkpropertyies[i].Name);
  542. }
  543. cmd.CommandText = strCmd;
  544. cmd.CommandType = CommandType.Text;
  545. cmd.Parameters.Clear();
  546. foreach (var property in fpkpropertyies)
  547. {
  548. object value = property.GetGetMethod().Invoke(modle, null);
  549. AddWithValue(cmd, "@" + property.Name, value);
  550. }
  551. return cmd.ExecuteNonQuery();
  552. }
  553. /// <summary>
  554. /// 异构对象插入数据库
  555. /// </summary>
  556. public static int Insert<TCommand, T>(TCommand cmd, string tablename, Dictionary<string, string> maps, T modle, string fields = "*") where TCommand : DbCommand
  557. {
  558. if (string.IsNullOrEmpty(tablename))
  559. {
  560. tablename = typeof(T).Name;
  561. }
  562. // DONE: 处理大小写问题
  563. var targetfields = GetTargetMaps<T>(maps, fields);
  564. cmd.CommandType = CommandType.Text;
  565. cmd.Parameters.Clear();
  566. string tablefields = string.Empty;
  567. string valuefields = string.Empty;
  568. foreach (var targetfield in targetfields)
  569. {
  570. if (string.IsNullOrEmpty(tablefields))
  571. {
  572. tablefields = targetfield.Key;
  573. valuefields = "@" + targetfield.Key;
  574. }
  575. else
  576. {
  577. tablefields += "," + targetfield.Key;
  578. valuefields += ",@" + targetfield.Key;
  579. }
  580. AddWithValue(cmd, "@" + targetfield.Key, targetfield.Value.GetGetMethod().Invoke(modle, null));
  581. }
  582. if (string.IsNullOrEmpty(tablefields))
  583. {
  584. throw new Exception("没有一个有效插入字段");
  585. }
  586. cmd.CommandText = string.Format("INSERT INTO {0}({1}) VALUES({2})", tablename, tablefields, valuefields);
  587. try
  588. {
  589. return cmd.ExecuteNonQuery();
  590. }
  591. catch (Exception ex)
  592. {
  593. Trace.Write(ex.ToString());
  594. Trace.Write(ModleToString(modle));
  595. throw;
  596. }
  597. }
  598. public static int Insert<TCommand, T>(TCommand cmd, T modle, string fields = "*") where TCommand : DbCommand
  599. {
  600. return Insert(cmd, null, null, modle, fields);
  601. ; }
  602. private static Dictionary<string, PropertyInfo> GetTargetMaps<T>(IDictionary<string, string> maps, string fields)
  603. {
  604. var newmaps = new Dictionary<string, string>();
  605. if (maps != null)
  606. {
  607. foreach (var map in maps)
  608. {
  609. newmaps[map.Key.Trim().ToLower()] = map.Value.Trim().ToLower();
  610. }
  611. }
  612. var targetfields = new Dictionary<string, PropertyInfo>();
  613. var orgfields = GetProperties(typeof (T));
  614. string[] arr_fields;
  615. if (fields.Equals("*"))
  616. {
  617. arr_fields = orgfields.Keys.ToArray();
  618. }
  619. else
  620. {
  621. arr_fields = fields.Split(',');
  622. }
  623. foreach (var field in arr_fields)
  624. {
  625. var key = field.Trim().ToLower();
  626. if (targetfields.ContainsKey(key))
  627. {
  628. continue;
  629. }
  630. if (newmaps.ContainsKey(key) && orgfields.ContainsKey(newmaps[key]))
  631. {
  632. targetfields[key] = orgfields[newmaps[key]];
  633. }
  634. else if (orgfields.ContainsKey(key))
  635. {
  636. targetfields[key] = orgfields[key];
  637. }
  638. }
  639. return targetfields;
  640. }
  641. public static int Update<TCommand, T>(TCommand cmd, string tablename, Dictionary<string, string> maps, T modle, string pkfields, string fields = "*") where TCommand : DbCommand
  642. {
  643. // DONE: 处理大小写问题
  644. var pkfields_dir = GetTargetMaps<T>(maps, pkfields);
  645. var targetfields = GetTargetMaps<T>(maps, fields);
  646. cmd.CommandType = CommandType.Text;
  647. cmd.Parameters.Clear();
  648. string keyFields = string.Empty;
  649. foreach (var targetfield in pkfields_dir)
  650. {
  651. if (string.IsNullOrEmpty(keyFields))
  652. {
  653. keyFields = string.Format("{0} = @{0}", targetfield.Key);
  654. }
  655. else
  656. {
  657. keyFields += string.Format(" AND {0} = @{0}", targetfield.Key);
  658. }
  659. AddWithValue(cmd, "@" + targetfield.Key, targetfield.Value.GetGetMethod().Invoke(modle, null));
  660. }
  661. if (string.IsNullOrEmpty(keyFields))
  662. {
  663. throw new Exception("没有一个有效的条件字段");
  664. }
  665. string setFields = string.Empty;
  666. foreach (var targetfield in targetfields)
  667. {
  668. if (string.IsNullOrEmpty(setFields))
  669. {
  670. setFields = string.Format("{0} = @{0}", targetfield.Key);
  671. }
  672. else
  673. {
  674. setFields += string.Format(", {0} = @{0}", targetfield.Key);
  675. }
  676. AddWithValue(cmd, "@" + targetfield.Key, targetfield.Value.GetGetMethod().Invoke(modle, null));
  677. }
  678. if (string.IsNullOrEmpty(setFields))
  679. {
  680. throw new Exception("没有一个有效更新字段");
  681. }
  682. cmd.CommandText = string.Format("UPDATE {0} SET {1} WHERE {2}", tablename, setFields, keyFields);
  683. try
  684. {
  685. return cmd.ExecuteNonQuery();
  686. }
  687. catch (Exception ex)
  688. {
  689. Trace.Write(ex.ToString());
  690. Trace.Write(ModleToString(modle));
  691. throw;
  692. }
  693. }
  694. public static int Update<TCommand, T>(TCommand cmd, T modle, string fields = "*") where TCommand : DbCommand
  695. {
  696. var pks = GetPKs(typeof(T));
  697. if (pks == null || pks.Length == 0)
  698. {
  699. throw new Exception(string.Format("当前类{0}没有定义关键字段", typeof(T).Name));
  700. }
  701. var pkfields = pks[0];
  702. if (pks.Length > 0)
  703. {
  704. foreach (var pk in pks)
  705. {
  706. if (string.IsNullOrEmpty(pk))
  707. {
  708. throw new Exception(string.Format("模型类{0}的主键不能为空", typeof(T).FullName));
  709. }
  710. var withnullpk = false;
  711. var pkproperties = GetProperties(typeof(T), pk);
  712. if (pkproperties.Count == 0)
  713. {
  714. throw new Exception(string.Format("模型类{0}的主键与字段名不符", typeof(T).FullName));
  715. }
  716. foreach (var propertyInfo in pkproperties)
  717. {
  718. var getMethod = propertyInfo.GetGetMethod();
  719. var value = getMethod.Invoke(modle, null);
  720. if (value == null)
  721. {
  722. withnullpk = true;
  723. break;
  724. }
  725. }
  726. if (!withnullpk)
  727. {
  728. pkfields = pk;
  729. break;
  730. }
  731. }
  732. }
  733. return Update(cmd, typeof (T).Name, null, modle, pkfields, fields);
  734. }
  735. public static int InsertOrUpdate<TCommand, T>(TCommand cmd, T modle, string fields = "*") where TCommand : DbCommand
  736. {
  737. try
  738. {
  739. // 查找非空主键
  740. var ifinsert = false;
  741. var pks = GetPKs(typeof(T));
  742. if (pks == null || pks.Length == 0)
  743. {
  744. ifinsert = true;
  745. }
  746. IList<PropertyInfo> fpkpropertyies = null;
  747. if (!ifinsert)
  748. {
  749. foreach (var pk in pks)
  750. {
  751. if (string.IsNullOrEmpty(pk))
  752. {
  753. throw new Exception(string.Format("模型类{0}的主键不能为空", typeof(T).FullName));
  754. }
  755. var withnullpk = false;
  756. var pkproperties = GetProperties(typeof(T), pk);
  757. if (pkproperties.Count == 0)
  758. {
  759. throw new Exception(string.Format("模型类{0}的主键与字段名不符", typeof(T).FullName));
  760. }
  761. foreach (var propertyInfo in pkproperties)
  762. {
  763. var getMethod = propertyInfo.GetGetMethod();
  764. var value = getMethod.Invoke(modle, null);
  765. if (value == null)
  766. {
  767. withnullpk = true;
  768. break;
  769. }
  770. }
  771. if (!withnullpk)
  772. {
  773. fpkpropertyies = pkproperties;
  774. break;
  775. }
  776. }
  777. if (fpkpropertyies == null)
  778. {
  779. ifinsert = true;
  780. }
  781. }
  782. List<PropertyInfo> propertyies = null;
  783. if (!ifinsert)
  784. {
  785. // 按主键更新
  786. propertyies = GetProperties(typeof(T), fields);
  787. if (propertyies.Count == 0)
  788. {
  789. propertyies = new List<PropertyInfo>(GetProperties(typeof(T)).Values);
  790. }
  791. var pknames = new HashSet<string>();
  792. foreach (var fpk in fpkpropertyies)
  793. {
  794. pknames.Add(fpk.Name);
  795. }
  796. for (int i = propertyies.Count - 1; i >= 0; i--)
  797. {
  798. if (pknames.Contains(propertyies[i].Name))
  799. {
  800. propertyies.RemoveAt(i);
  801. }
  802. }
  803. if (propertyies.Count == 0)
  804. {
  805. string strCmd = string.Format("SELECT COUNT(0) FROM " + typeof(T).Name + " WHERE {0}=@{0}", fpkpropertyies[0].Name);
  806. for (int i = 1; i < fpkpropertyies.Count; i++)
  807. {
  808. strCmd += string.Format(" AND {0}=@{0}", fpkpropertyies[i].Name);
  809. }
  810. cmd.CommandText = strCmd;
  811. cmd.CommandType = CommandType.Text;
  812. cmd.Parameters.Clear();
  813. foreach (var pk in fpkpropertyies)
  814. {
  815. object value = pk.GetGetMethod().Invoke(modle, null);
  816. AddWithValue(cmd, "@" + pk.Name, value);
  817. }
  818. var cnt = Convert.ToUInt32(cmd.ExecuteScalar());
  819. if (cnt == 0)
  820. {
  821. ifinsert = true;
  822. }
  823. }
  824. else
  825. {
  826. string strCmd = string.Format("UPDATE " + typeof(T).Name + " SET {0}=@{0}", propertyies[0].Name);
  827. for (int i = 1; i < propertyies.Count; i++)
  828. {
  829. strCmd += string.Format(",{0}=@{0}", propertyies[i].Name);
  830. }
  831. strCmd += string.Format(" WHERE {0}=@{0}", fpkpropertyies[0].Name);
  832. for (int i = 1; i < fpkpropertyies.Count; i++)
  833. {
  834. strCmd += string.Format(" AND {0}=@{0}", fpkpropertyies[i].Name);
  835. }
  836. cmd.CommandText = strCmd;
  837. cmd.CommandType = CommandType.Text;
  838. cmd.Parameters.Clear();
  839. foreach (var pk in fpkpropertyies)
  840. {
  841. object value = pk.GetGetMethod().Invoke(modle, null);
  842. AddWithValue(cmd, "@" + pk.Name, value);
  843. }
  844. foreach (var field in propertyies)
  845. {
  846. object value = field.GetGetMethod().Invoke(modle, null);
  847. AddWithValue(cmd, "@" + field.Name, value);
  848. }
  849. var cnt = cmd.ExecuteNonQuery();
  850. if (cnt == 0)
  851. {
  852. ifinsert = true;
  853. }
  854. else
  855. {
  856. return cnt;
  857. }
  858. }
  859. }
  860. if (ifinsert)
  861. {
  862. // 插入
  863. if (propertyies == null) // 只有在无主键的情况下才会为空
  864. {
  865. propertyies = GetProperties(typeof(T), fields);
  866. if (propertyies.Count == 0)
  867. {
  868. propertyies = new List<PropertyInfo>(GetProperties(typeof(T)).Values);
  869. }
  870. }
  871. if (fpkpropertyies != null)
  872. {
  873. propertyies.AddRange(fpkpropertyies);
  874. }
  875. if (propertyies.Count == 0)
  876. {
  877. throw new Exception(string.Format("模型{0}没有字段定义", typeof(T).FullName));
  878. }
  879. string strCmd = string.Format("INSERT INTO " + typeof(T).Name + "({0}", propertyies[0].Name);
  880. for (int i = 1; i < propertyies.Count; i++)
  881. {
  882. strCmd += string.Format(",{0}", propertyies[i].Name);
  883. }
  884. strCmd += string.Format(") VALUES(@{0}", propertyies[0].Name);
  885. for (int i = 1; i < propertyies.Count; i++)
  886. {
  887. strCmd += string.Format(",@{0}", propertyies[i].Name);
  888. }
  889. strCmd += ")";
  890. cmd.CommandText = strCmd;
  891. cmd.CommandType = CommandType.Text;
  892. cmd.Parameters.Clear();
  893. foreach (var field in propertyies)
  894. {
  895. object value = field.GetGetMethod().Invoke(modle, null);
  896. AddWithValue(cmd, "@" + field.Name, value);
  897. }
  898. return cmd.ExecuteNonQuery();
  899. }
  900. return 0;
  901. }
  902. catch (Exception ex)
  903. {
  904. Trace.Write(ex.ToString());
  905. Trace.Write(ModleToString(modle));
  906. throw;
  907. }
  908. }
  909. private static object ModleToString(object modle)
  910. {
  911. if (modle == null)
  912. {
  913. return "{}";
  914. }
  915. var list = GetProperties(modle.GetType()).Values;
  916. StringBuilder rslt = new StringBuilder();
  917. rslt.Append(modle.GetType().ToString() + ":{");
  918. bool hasone = false;
  919. foreach (var pro in list)
  920. {
  921. var getMethod = pro.GetGetMethod();
  922. if (getMethod == null)
  923. {
  924. continue;
  925. }
  926. var value = getMethod.Invoke(modle, null);
  927. var curent = string.Format("{0}:\"{1}\"", pro.Name, value ?? "nil");
  928. if (!hasone)
  929. {
  930. rslt.Append(curent);
  931. hasone = true;
  932. }
  933. else
  934. {
  935. rslt.Append("," + curent);
  936. }
  937. }
  938. rslt.Append("}");
  939. return rslt.ToString();
  940. }
  941. private static List<PropertyInfo> GetProperties(Type type, string outputFields)
  942. {
  943. List<PropertyInfo> rslt = new List<PropertyInfo>();
  944. Dictionary<string, PropertyInfo> properties = GetProperties(type);
  945. string[] fields = outputFields.Split(',');
  946. foreach (string field in fields)
  947. {
  948. string key = field.Trim().ToLower();
  949. if (properties.ContainsKey(key))
  950. {
  951. rslt.Add(properties[key]);
  952. }
  953. }
  954. return rslt;
  955. }
  956. private static Dictionary<Type, Dictionary<string, PropertyInfo>> _typeinfoCache = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
  957. private static object _syncRoot_typeinfoCache = new object();
  958. private static Dictionary<string, PropertyInfo> GetProperties(Type type)
  959. {
  960. lock (_syncRoot_typeinfoCache)
  961. {
  962. if (_typeinfoCache.ContainsKey(type))
  963. {
  964. return _typeinfoCache[type];
  965. }
  966. PropertyInfo[] properties = type.GetProperties();
  967. Dictionary<string, PropertyInfo> dirProperties = new Dictionary<string, PropertyInfo>();
  968. foreach (PropertyInfo property in properties)
  969. {
  970. string key = property.Name.Trim().ToLower();
  971. if (!dirProperties.ContainsKey(key))
  972. {
  973. dirProperties[key] = property;
  974. }
  975. }
  976. _typeinfoCache[type] = dirProperties;
  977. return dirProperties;
  978. }
  979. }
  980. private static Dictionary<Type, ISqlEngine> _cmd_engines = new Dictionary<Type, ISqlEngine>();
  981. private static object _eng_root = new object();
  982. public static void Add<T>(SqlEngine<T> engine) where T : DbCommand
  983. {
  984. if (engine == null)
  985. {
  986. throw new Exception("engine参数不能为null");
  987. }
  988. lock (_eng_root)
  989. {
  990. _cmd_engines[typeof(T)] = engine;
  991. }
  992. }
  993. private static ISqlEngine GetEngine(Type type)
  994. {
  995. lock (_eng_root)
  996. {
  997. if (!_cmd_engines.ContainsKey(type))
  998. {
  999. throw new Exception(string.Format("{0}未关联数据库引擎", type.FullName));
  1000. }
  1001. return _cmd_engines[type];
  1002. }
  1003. }
  1004. }
  1005. }