SqlHelper.cs 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.SqlClient;
  5. using System.Diagnostics;
  6. using System.Reflection;
  7. using System.Text;
  8. using System.Text.RegularExpressions;
  9. namespace LJLib.DAL.SQL
  10. {
  11. internal static class SqlHelper
  12. {
  13. public static DateTime GetServerTime(SqlCommand cmd)
  14. {
  15. cmd.CommandText = "SELECT GETDATE()";
  16. cmd.CommandType = CommandType.Text;
  17. cmd.Parameters.Clear();
  18. return Convert.ToDateTime(cmd.ExecuteScalar());
  19. }
  20. public static bool DataBaseExists(string ConnectionString, string dbname)
  21. {
  22. SqlConnectionStringBuilder builer = new SqlConnectionStringBuilder(ConnectionString);
  23. builer.InitialCatalog = "master";
  24. using (SqlConnection con = new SqlConnection(builer.ConnectionString))
  25. {
  26. con.Open();
  27. SqlCommand cmd = con.CreateCommand();
  28. cmd.CommandText = "SELECT COUNT(0) from sysdatabases WHERE name = @name";
  29. cmd.Parameters.Clear();
  30. cmd.Parameters.Add("@name", SqlDbType.VarChar).Value = dbname;
  31. int cnt = Convert.ToInt32(cmd.ExecuteScalar());
  32. return cnt > 0;
  33. }
  34. }
  35. public static void CreateDataBase(string ConnectionString, string dbname)
  36. {
  37. SqlConnectionStringBuilder builer = new SqlConnectionStringBuilder(ConnectionString);
  38. builer.InitialCatalog = "master";
  39. using (SqlConnection con = new SqlConnection(builer.ConnectionString))
  40. {
  41. con.Open();
  42. SqlCommand cmd = con.CreateCommand();
  43. cmd.CommandText = "CREATE DATABASE " + dbname;
  44. cmd.ExecuteNonQuery();
  45. }
  46. }
  47. public static int SelectCount(SqlCommand cmd, string table, string wherestr, IEnumerable<SqlParameter> sqlparams = null)
  48. {
  49. string strcmd = "SELECT COUNT(0) FROM " + table;
  50. if (!string.IsNullOrEmpty(wherestr))
  51. {
  52. wherestr = wherestr.Trim();
  53. strcmd += " WHERE " + wherestr;
  54. }
  55. cmd.CommandText = strcmd;
  56. cmd.CommandType = CommandType.Text;
  57. cmd.Parameters.Clear();
  58. if (sqlparams != null)
  59. {
  60. foreach (SqlParameter sqlparam in sqlparams)
  61. {
  62. if (sqlparam.Value == null)
  63. {
  64. sqlparam.Value = DBNull.Value;
  65. }
  66. cmd.Parameters.Add(sqlparam);
  67. }
  68. }
  69. return Convert.ToInt32(cmd.ExecuteScalar());
  70. }
  71. public static int Select<T>(SqlCommand cmd, IList<T> modles, string wherestr, string fields = "*") where T : ModleBase, new()
  72. {
  73. return Select(cmd, modles, wherestr, null, null, fields, 0, 0);
  74. }
  75. public static int Select<T>(SqlCommand cmd, IList<T> modles, string wherestr, IEnumerable<SqlParameter> sqlparams, string fields = "*") where T : ModleBase, new()
  76. {
  77. return Select(cmd, modles, wherestr, sqlparams, null, fields, 0, 0);
  78. }
  79. public static int Select<T>(SqlCommand cmd, IList<T> modles, string whereStr, IEnumerable<SqlParameter> sqlparams, string orderByStr, string outputFields, int pageindex, int pagesize) where T : ModleBase, new()
  80. {
  81. if (modles.IsReadOnly)
  82. {
  83. throw new ArgumentException("参数modles不能为只读");
  84. }
  85. ModleInfo info = GetModleInfo(typeof(T));
  86. string strCmd = BuildSelectCmd(info);
  87. PrepareSelectCmd(cmd, strCmd, whereStr, sqlparams, ref outputFields, orderByStr, pageindex, pagesize);
  88. IList<FieldInfo> fields = GetFields(info, outputFields);
  89. using (SqlDataReader reader = cmd.ExecuteReader())
  90. {
  91. while (reader.Read())
  92. {
  93. T modle = new T();
  94. foreach (FieldInfo field in fields)
  95. {
  96. object value = null;
  97. try
  98. {
  99. value = reader[field.FieldName];
  100. }
  101. catch (Exception)
  102. {
  103. continue;
  104. }
  105. if (value == null || value == DBNull.Value)
  106. {
  107. continue;
  108. }
  109. if (value is string)
  110. {
  111. value = value.ToString().Trim();
  112. }
  113. value = ConvertValue(field.SetMethod.GetParameters()[0].ParameterType, value);
  114. field.SetMethod.Invoke(modle, new object[] { value });
  115. }
  116. modles.Add(modle);
  117. }
  118. return modles.Count;
  119. }
  120. }
  121. private static IList<FieldInfo> GetFields(ModleInfo info, string outputFields)
  122. {
  123. List<FieldInfo> rslt = new List<FieldInfo>();
  124. string[] fields = outputFields.Split(',');
  125. foreach (string field in fields)
  126. {
  127. string key = field.Trim().ToLower();
  128. if (info.Fields.ContainsKey(key))
  129. {
  130. rslt.Add(info.Fields[key]);
  131. }
  132. }
  133. return rslt;
  134. }
  135. private static string BuildSelectCmd(ModleInfo info)
  136. {
  137. string fields = string.Empty;
  138. foreach (FieldInfo field in info.Fields.Values)
  139. {
  140. if (string.IsNullOrEmpty(fields))
  141. {
  142. fields = field.FieldName;
  143. }
  144. else
  145. {
  146. fields += "," + field.FieldName;
  147. }
  148. }
  149. return "SELECT " + fields + " FROM " + info.TableName;
  150. }
  151. public static int Select<T>(SqlCommand cmd, IList<T> modles, string wherestr, IEnumerable<SqlParameter> sqlparams, int pageindex, int pagesize, string orderstr, string fields = "*") where T : ModleBase, new()
  152. {
  153. return Select(cmd, modles, wherestr, sqlparams, orderstr, fields, pageindex, pagesize);
  154. }
  155. public static int SelectOne<T>(SqlCommand cmd, T modle, string fields = "*") where T : ModleBase
  156. {
  157. ModleInfo info = GetModleInfo(typeof(T));
  158. Dictionary<string, FieldInfo> allFields = new Dictionary<string, FieldInfo>();
  159. Dictionary<string, FieldInfo> dictNonPrimaryKeys = new Dictionary<string, FieldInfo>();
  160. info.GetFields(fields, allFields, dictNonPrimaryKeys);
  161. List<FieldInfo> nonPrimaryKeys = new List<FieldInfo>(dictNonPrimaryKeys.Values);
  162. SelectCommandText(cmd, info.TableName, info.PrimaryKeys, nonPrimaryKeys);
  163. AddParameters(cmd, modle, info.PrimaryKeys);
  164. using (SqlDataReader reader = cmd.ExecuteReader())
  165. {
  166. if (!reader.Read())
  167. {
  168. return 0;
  169. }
  170. foreach (FieldInfo field in nonPrimaryKeys)
  171. {
  172. object value = reader[field.FieldName];
  173. if (value == DBNull.Value)
  174. {
  175. value = null;
  176. }
  177. if (value != null && value is string)
  178. {
  179. value = value.ToString().Trim();
  180. }
  181. if (value != null)
  182. {
  183. value = ConvertValue(field.SetMethod.GetParameters()[0].ParameterType, value);
  184. }
  185. field.SetMethod.Invoke(modle, new object[] { value });
  186. }
  187. return 1;
  188. }
  189. }
  190. public static int Delete<T>(SqlCommand cmd, T modle) where T : ModleBase
  191. {
  192. ModleInfo info = GetModleInfo(typeof(T));
  193. DeleteCommandText(cmd, info.TableName, info.PrimaryKeys);
  194. AddParameters(cmd, modle, info.PrimaryKeys);
  195. return cmd.ExecuteNonQuery();
  196. }
  197. private static void DeleteCommandText(SqlCommand cmd, string tablename, List<FieldInfo> list)
  198. {
  199. string strcmd = "DELETE FROM " + tablename + " WHERE " + list[0].FieldName + "=@" + list[0].FieldName;
  200. for (int i = 1; i < list.Count; i++)
  201. {
  202. strcmd += " AND " + list[i].FieldName + "=@" + list[i].FieldName;
  203. }
  204. cmd.CommandType = CommandType.Text;
  205. cmd.CommandText = strcmd;
  206. }
  207. public static void BulkInsert<T>(SqlCommand cmd, IEnumerable<T> modles, string fields = "*")
  208. {
  209. ModleInfo info = GetModleInfo(typeof(T));
  210. Dictionary<string, FieldInfo> allFields = new Dictionary<string, FieldInfo>();
  211. Dictionary<string, FieldInfo> dictNonPrimaryKeys = new Dictionary<string, FieldInfo>();
  212. info.GetFields(fields, allFields, dictNonPrimaryKeys);
  213. using (DataTable dt = new DataTable())
  214. {
  215. int cnt = 0;
  216. foreach (var field in info.PrimaryKeys)
  217. {
  218. var col = new DataColumn(field.FieldName);
  219. col.AllowDBNull = true;
  220. var rtType = field.GetMethod.ReturnType;
  221. if (rtType.IsGenericType)
  222. {
  223. Type GT = rtType.GetGenericTypeDefinition();
  224. Type BT = rtType.GetGenericArguments()[0];
  225. if (GT == typeof(Nullable<>))
  226. {
  227. rtType = BT;
  228. }
  229. }
  230. col.DataType = rtType;
  231. dt.Columns.Add(col);
  232. cnt++;
  233. }
  234. foreach (var kvp in dictNonPrimaryKeys)
  235. {
  236. var col = new DataColumn(kvp.Value.FieldName);
  237. col.AllowDBNull = true;
  238. var rtType = kvp.Value.GetMethod.ReturnType;
  239. if (rtType.IsGenericType)
  240. {
  241. Type GT = rtType.GetGenericTypeDefinition();
  242. Type BT = rtType.GetGenericArguments()[0];
  243. if (GT == typeof(Nullable<>))
  244. {
  245. rtType = BT;
  246. }
  247. }
  248. col.DataType = rtType;
  249. dt.Columns.Add(col);
  250. cnt++;
  251. }
  252. foreach (var model in modles)
  253. {
  254. var values = new object[cnt];
  255. int i = 0;
  256. foreach (var field in info.PrimaryKeys)
  257. {
  258. values[i] = field.GetMethod.Invoke(model, null);
  259. if (values[i] == null)
  260. {
  261. values[i] = DBNull.Value;
  262. }
  263. i++;
  264. }
  265. foreach (var kvp in dictNonPrimaryKeys)
  266. {
  267. values[i] = kvp.Value.GetMethod.Invoke(model, null);
  268. if (values[i] == null)
  269. {
  270. values[i] = DBNull.Value;
  271. }
  272. i++;
  273. }
  274. dt.Rows.Add(values);
  275. }
  276. using (SqlBulkCopy sqlBC = new SqlBulkCopy(cmd.Connection))
  277. {
  278. //一次批量的插入的数据量
  279. sqlBC.BatchSize = 1000;
  280. //超时之前操作完成所允许的秒数,如果超时则事务不会提交 ,数据将回滚,所有已复制的行都会从目标表中移除
  281. sqlBC.BulkCopyTimeout = 60;
  282. ////設定 NotifyAfter 属性,以便在每插入10000 条数据时,呼叫相应事件。
  283. //sqlBC.NotifyAfter = 10000;
  284. //sqlBC.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied);
  285. //设置要批量写入的表
  286. sqlBC.DestinationTableName = info.TableName;
  287. //自定义的datatable和数据库的字段进行对应
  288. foreach (var field in info.PrimaryKeys)
  289. {
  290. sqlBC.ColumnMappings.Add(field.FieldName, field.FieldName);
  291. }
  292. foreach (var kvp in dictNonPrimaryKeys)
  293. {
  294. sqlBC.ColumnMappings.Add(kvp.Value.FieldName, kvp.Value.FieldName);
  295. }
  296. //批量写入
  297. sqlBC.WriteToServer(dt);
  298. }
  299. }
  300. }
  301. public static int InsertOrUpdate<T>(SqlCommand cmd, T modle, string fields = "*") where T : ModleBase
  302. {
  303. ModleInfo info = GetModleInfo(typeof(T));
  304. Dictionary<string, FieldInfo> allFields = new Dictionary<string, FieldInfo>();
  305. Dictionary<string, FieldInfo> dictNonPrimaryKeys = new Dictionary<string, FieldInfo>();
  306. info.GetFields(fields, allFields, dictNonPrimaryKeys);
  307. List<FieldInfo> nonPrimaryKeys = new List<FieldInfo>(dictNonPrimaryKeys.Values);
  308. try
  309. {
  310. if (nonPrimaryKeys.Count > 0 && info.PrimaryKeys.Count > 0)
  311. {
  312. bool withnonkey = false;
  313. if (info.PrimaryKeys.Count == 1)
  314. {
  315. withnonkey = info.PrimaryKeys[0].GetMethod.Invoke(modle, null) == null;
  316. }
  317. if (withnonkey)
  318. {
  319. InsertCommandText(cmd, info.TableName, nonPrimaryKeys);
  320. AddParameters(cmd, modle, nonPrimaryKeys);
  321. cmd.CommandText += ";select @@IDENTITY";
  322. object id = cmd.ExecuteScalar();
  323. if (info.PrimaryKeys[0].DbType == SqlDbType.BigInt)
  324. {
  325. info.PrimaryKeys[0].SetMethod.Invoke(modle, new object[] { Convert.ToInt64(id) });
  326. }
  327. else if (info.PrimaryKeys[0].DbType == SqlDbType.Int)
  328. {
  329. info.PrimaryKeys[0].SetMethod.Invoke(modle, new object[] { Convert.ToInt32(id) });
  330. }
  331. else
  332. {
  333. info.PrimaryKeys[0].SetMethod.Invoke(modle, new object[] { id });
  334. }
  335. return 1;
  336. }
  337. else
  338. {
  339. UpdateCommandText(cmd, info.TableName, info.PrimaryKeys, nonPrimaryKeys);
  340. AddParameters(cmd, modle, info.PrimaryKeys, nonPrimaryKeys);
  341. int cnt = cmd.ExecuteNonQuery();
  342. if (cnt == 0)
  343. {
  344. InsertCommandText(cmd, info.TableName, info.PrimaryKeys, nonPrimaryKeys);
  345. AddParameters(cmd, modle, info.PrimaryKeys, nonPrimaryKeys);
  346. return cmd.ExecuteNonQuery();
  347. }
  348. else
  349. {
  350. return cnt;
  351. }
  352. }
  353. }
  354. else if (nonPrimaryKeys.Count > 0)
  355. {
  356. InsertCommandText(cmd, info.TableName, nonPrimaryKeys);
  357. AddParameters(cmd, modle, nonPrimaryKeys);
  358. return cmd.ExecuteNonQuery();
  359. }
  360. else if (info.PrimaryKeys.Count > 0)
  361. {
  362. InsertCommandText(cmd, info.TableName, info.PrimaryKeys);
  363. AddParameters(cmd, modle, info.PrimaryKeys);
  364. return cmd.ExecuteNonQuery();
  365. }
  366. else
  367. {
  368. return 0;
  369. }
  370. }
  371. catch (Exception)
  372. {
  373. Trace.Write(ModleToString(modle, info.PrimaryKeys, nonPrimaryKeys));
  374. throw;
  375. }
  376. }
  377. private static object ModleToString(object modle, List<FieldInfo> list, List<FieldInfo> nonPrimaryKeys)
  378. {
  379. StringBuilder rslt = new StringBuilder();
  380. rslt.Append(modle.GetType().ToString() + ":{");
  381. bool hasone = false;
  382. int i;
  383. if (list.Count > 0)
  384. {
  385. hasone = true;
  386. rslt.Append(string.Format("{0}:\"{1}\"", list[0].FieldName,
  387. list[0].GetMethod.Invoke(modle, null) ?? string.Empty));
  388. for (i = 1; i < list.Count; i++)
  389. {
  390. rslt.Append(string.Format(",{0}:\"{1}\"", list[i].FieldName,
  391. list[i].GetMethod.Invoke(modle, null) ?? string.Empty));
  392. }
  393. }
  394. i = 0;
  395. if (!hasone && nonPrimaryKeys.Count > 0)
  396. {
  397. rslt.Append(string.Format("{0}:\"{1}\"", nonPrimaryKeys[0].FieldName,
  398. nonPrimaryKeys[0].GetMethod.Invoke(modle, null) ?? string.Empty));
  399. i = 1;
  400. }
  401. for (; i < nonPrimaryKeys.Count; i++)
  402. {
  403. rslt.Append(string.Format(",{0}:\"{1}\"", nonPrimaryKeys[i].FieldName,
  404. nonPrimaryKeys[i].GetMethod.Invoke(modle, null) ?? string.Empty));
  405. }
  406. return rslt.ToString();
  407. }
  408. private static void InsertCommandText(SqlCommand cmd, string tablename, params List<FieldInfo>[] list)
  409. {
  410. string strfields = string.Empty;
  411. string strvalues = string.Empty;
  412. bool first = true;
  413. foreach (List<FieldInfo> fields in list)
  414. {
  415. foreach (FieldInfo field in fields)
  416. {
  417. if (first)
  418. {
  419. strfields = field.FieldName;
  420. strvalues = "@" + field.FieldName;
  421. first = false;
  422. }
  423. else
  424. {
  425. strfields += "," + field.FieldName;
  426. strvalues += ",@" + field.FieldName;
  427. }
  428. }
  429. }
  430. cmd.CommandType = CommandType.Text;
  431. cmd.CommandText = "INSERT INTO " + tablename + "(" + strfields + ") VALUES(" + strvalues + ")";
  432. }
  433. private static void UpdateCommandText(SqlCommand cmd, string tablename, List<FieldInfo> primaryKeys, List<FieldInfo> nonPrimaryKeys)
  434. {
  435. string strcmd = "UPDATE " + tablename + " SET " + nonPrimaryKeys[0].FieldName + "=@" + nonPrimaryKeys[0].FieldName;
  436. for (int i = 1; i < nonPrimaryKeys.Count; i++)
  437. {
  438. strcmd += "," + nonPrimaryKeys[i].FieldName + "=@" + nonPrimaryKeys[i].FieldName;
  439. }
  440. strcmd += " WHERE " + primaryKeys[0].FieldName + "=@" + primaryKeys[0].FieldName;
  441. for (int i = 1; i < primaryKeys.Count; i++)
  442. {
  443. strcmd += " AND " + primaryKeys[i].FieldName + "=@" + primaryKeys[i].FieldName;
  444. }
  445. cmd.CommandType = CommandType.Text;
  446. cmd.CommandText = strcmd;
  447. }
  448. private static void SelectCommandText(SqlCommand cmd, string tablename, List<FieldInfo> primaryKeys, List<FieldInfo> nonPrimaryKeys)
  449. {
  450. string strcmd = "SELECT " + nonPrimaryKeys[0].FieldName;
  451. for (int i = 1; i < nonPrimaryKeys.Count; i++)
  452. {
  453. strcmd += "," + nonPrimaryKeys[i].FieldName;
  454. }
  455. strcmd += " FROM " + tablename;
  456. strcmd += " WHERE " + primaryKeys[0].FieldName + "=@" + primaryKeys[0].FieldName;
  457. for (int i = 1; i < primaryKeys.Count; i++)
  458. {
  459. strcmd += " AND " + primaryKeys[i].FieldName + "=@" + primaryKeys[i].FieldName;
  460. }
  461. cmd.CommandType = CommandType.Text;
  462. cmd.CommandText = strcmd;
  463. }
  464. private static void SelectCommandText(SqlCommand cmd, string tablename, IEnumerable<FieldInfo> fields, string wherestr)
  465. {
  466. bool first = true;
  467. string strcmd = "SELECT ";
  468. foreach (FieldInfo field in fields)
  469. {
  470. if (first)
  471. {
  472. first = false;
  473. strcmd += field.FieldName;
  474. }
  475. else
  476. {
  477. strcmd += "," + field.FieldName;
  478. }
  479. }
  480. strcmd += " FROM " + tablename;
  481. wherestr = wherestr.Trim();
  482. if (!string.IsNullOrEmpty(wherestr))
  483. {
  484. strcmd += " WHERE " + wherestr;
  485. }
  486. cmd.CommandType = CommandType.Text;
  487. cmd.CommandText = strcmd;
  488. }
  489. private static void AddParameters(SqlCommand cmd, object modle, params List<FieldInfo>[] list)
  490. {
  491. cmd.Parameters.Clear();
  492. foreach (List<FieldInfo> fields in list)
  493. {
  494. foreach (FieldInfo field in fields)
  495. {
  496. object value = field.GetMethod.Invoke(modle, null);
  497. cmd.Parameters.Add("@" + field.FieldName, field.DbType).Value = value == null ? DBNull.Value : value;
  498. }
  499. }
  500. }
  501. private static Dictionary<string, ModleInfo> modleinfos = new Dictionary<string, ModleInfo>();
  502. private static object modleinfos_syncRoot = new object();
  503. private static ModleInfo GetModleInfo(Type type)
  504. {
  505. lock (modleinfos_syncRoot)
  506. {
  507. string typename = type.FullName;
  508. if (modleinfos.ContainsKey(typename))
  509. {
  510. return modleinfos[typename];
  511. }
  512. Table table = type.GetCustomAttributes(typeof(Table), false)[0] as Table;
  513. ModleInfo rslt = new ModleInfo();
  514. rslt.TableName = table.Name;
  515. PropertyInfo[] properties = type.GetProperties();
  516. Dictionary<string, FieldInfo> fields = new Dictionary<string, FieldInfo>();
  517. List<FieldInfo> primaryKeys = new List<FieldInfo>();
  518. foreach (PropertyInfo property in properties)
  519. {
  520. object[] attrs = property.GetCustomAttributes(typeof(Field), false);
  521. if (attrs.Length <= 0)
  522. {
  523. continue;
  524. }
  525. Field field = attrs[0] as Field;
  526. FieldInfo fieldinfo = new FieldInfo();
  527. fieldinfo.FieldName = field.Name;
  528. fieldinfo.DbType = field.DbType;
  529. fieldinfo.IsPrimaryKey = field.IsPrimaryKey;
  530. fieldinfo.GetMethod = property.GetGetMethod();
  531. fieldinfo.SetMethod = property.GetSetMethod();
  532. fields.Add(property.Name.ToLower(), fieldinfo);
  533. if (fieldinfo.IsPrimaryKey)
  534. {
  535. primaryKeys.Add(fieldinfo);
  536. }
  537. }
  538. rslt.Fields = fields;
  539. rslt.PrimaryKeys = primaryKeys;
  540. modleinfos.Add(typename, rslt);
  541. return rslt;
  542. }
  543. }
  544. private class ModleInfo
  545. {
  546. public string TableName { get; set; }
  547. public Dictionary<string, FieldInfo> Fields { get; set; }
  548. public List<FieldInfo> PrimaryKeys { get; set; }
  549. public string GetFields(string strfields)
  550. {
  551. Dictionary<string, FieldInfo> AllFields = new Dictionary<string, FieldInfo>();
  552. if (strfields == "*")
  553. {
  554. foreach (KeyValuePair<string, FieldInfo> field in Fields)
  555. {
  556. AllFields.Add(field.Key, field.Value);
  557. }
  558. }
  559. else
  560. {
  561. string[] fields = strfields.Split(',');
  562. foreach (string str in fields)
  563. {
  564. string field = str.Trim();
  565. if (string.IsNullOrEmpty(field))
  566. {
  567. continue;
  568. }
  569. if (!Fields.ContainsKey(field))
  570. {
  571. continue;
  572. }
  573. if (AllFields.ContainsKey(field))
  574. {
  575. continue;
  576. }
  577. FieldInfo fieldinfo = Fields[field];
  578. AllFields[field] = fieldinfo;
  579. }
  580. }
  581. string rslt = string.Empty;
  582. foreach (KeyValuePair<string, FieldInfo> kvp in AllFields)
  583. {
  584. if (string.IsNullOrEmpty(rslt))
  585. {
  586. rslt = kvp.Value.FieldName;
  587. }
  588. else
  589. {
  590. rslt += "," + kvp.Value.FieldName;
  591. }
  592. }
  593. return rslt;
  594. }
  595. public void GetFields(string strfields, Dictionary<string, FieldInfo> AllFields, Dictionary<string, FieldInfo> nonPrimaryKeys)
  596. {
  597. if (string.IsNullOrEmpty(strfields) || strfields == "*")
  598. {
  599. foreach (KeyValuePair<string, FieldInfo> field in Fields)
  600. {
  601. AllFields.Add(field.Key, field.Value);
  602. if (!field.Value.IsPrimaryKey)
  603. {
  604. nonPrimaryKeys.Add(field.Key, field.Value);
  605. }
  606. }
  607. }
  608. else
  609. {
  610. string[] fields = strfields.Split(',');
  611. foreach (string str in fields)
  612. {
  613. string field = str.Trim().ToLower();
  614. if (string.IsNullOrEmpty(field))
  615. {
  616. continue;
  617. }
  618. if (!Fields.ContainsKey(field))
  619. {
  620. continue;
  621. }
  622. if (AllFields.ContainsKey(field))
  623. {
  624. continue;
  625. }
  626. FieldInfo fieldinfo = Fields[field];
  627. AllFields[field] = fieldinfo;
  628. if (fieldinfo.IsPrimaryKey)
  629. {
  630. continue;
  631. }
  632. nonPrimaryKeys.Add(field, fieldinfo);
  633. }
  634. }
  635. }
  636. }
  637. private class FieldInfo
  638. {
  639. public string FieldName { get; set; }
  640. public SqlDbType DbType { get; set; }
  641. public bool IsPrimaryKey { get; set; }
  642. public MethodInfo GetMethod { get; set; }
  643. public MethodInfo SetMethod { get; set; }
  644. }
  645. private static void MakeSelectCmd(SqlCommand cmd, string orgCmdStr, ref string preOutFieldStr, string orgWhereStr, string preOrderStr, int pageindex, int pagesize, IEnumerable<SqlParameter> sqlparams)
  646. {
  647. Regex regex = new Regex(@"\bselect\s+(.+?)\s+from\s+(.*)", RegexOptions.IgnoreCase | RegexOptions.Singleline);
  648. Match match = regex.Match(orgCmdStr);
  649. string outCmdStr = string.Empty;
  650. if (match.Success)
  651. {
  652. string orgFieldStr = match.Groups[1].Value.Trim();
  653. string orgFromStr = match.Groups[2].Value.Trim();
  654. Dictionary<string, string> orgFields = new Dictionary<string, string>();
  655. Dictionary<string, string> orgOrderFields = new Dictionary<string, string>();
  656. AnalyseFields(orgFieldStr, orgFields, orgOrderFields);
  657. string outFieldStr = BuildSelectFields(orgFields, preOutFieldStr);
  658. string outOrderStr = BuildOrderFields(orgOrderFields, preOrderStr);
  659. outCmdStr = outFieldStr + " FROM " + orgFromStr;
  660. if (!string.IsNullOrEmpty(orgWhereStr))
  661. {
  662. outCmdStr += " WHERE " + orgWhereStr;
  663. }
  664. if (!string.IsNullOrEmpty(outOrderStr))
  665. {
  666. outCmdStr += " ORDER BY " + outOrderStr;
  667. }
  668. preOutFieldStr = BuildSelectFieldNames(orgFields, preOutFieldStr);
  669. if (pageindex > 0 && pagesize > 0)
  670. {
  671. outCmdStr = "SELECT TOP " + (pageindex * pagesize).ToString() + " " + outCmdStr;
  672. string outFieldNameStr = preOutFieldStr;
  673. outCmdStr = "SELECT RowNumber = IDENTITY(INT,1, 1)," + outFieldNameStr + " INTO #tmp_sorttable FROM (" + outCmdStr + @") a
  674. SELECT TOP " + pagesize.ToString() + " " + outFieldNameStr + @" FROM #tmp_sorttable WHERE RowNumber > " + (pagesize * (pageindex - 1)).ToString() + @" ORDER BY RowNumber
  675. DROP TABLE #tmp_sorttable";
  676. }
  677. else if (pageindex <= 0 && pagesize > 0)
  678. {
  679. outCmdStr = "SELECT TOP " + pagesize + " " + outCmdStr;
  680. }
  681. else
  682. {
  683. outCmdStr = "SELECT " + outCmdStr;
  684. }
  685. cmd.CommandText = outCmdStr;
  686. cmd.CommandType = CommandType.Text;
  687. cmd.Parameters.Clear();
  688. if (sqlparams != null)
  689. {
  690. foreach (SqlParameter parm in sqlparams)
  691. {
  692. cmd.Parameters.Add(parm);
  693. }
  694. }
  695. }
  696. else
  697. {
  698. throw new Exception("MakeSelectCmd分析出现问题");
  699. }
  700. }
  701. private static string BuildSelectFieldNames(Dictionary<string, string> orgFields, string preOutFieldStr)
  702. {
  703. string outFieldStr = string.Empty;
  704. Dictionary<string, string> outFields = new Dictionary<string, string>();
  705. if (!string.IsNullOrEmpty(preOutFieldStr))
  706. {
  707. string[] fields = preOutFieldStr.Split(',');
  708. foreach (string field in fields)
  709. {
  710. string key = field.Trim().ToLower();
  711. if (orgFields.ContainsKey(key) && !outFields.ContainsKey(key))
  712. {
  713. outFields[key] = orgFields[key];
  714. }
  715. }
  716. }
  717. if (outFields.Count == 0)
  718. {
  719. outFields = orgFields;
  720. }
  721. foreach (KeyValuePair<string, string> kvp in outFields)
  722. {
  723. if (string.IsNullOrEmpty(outFieldStr))
  724. {
  725. outFieldStr = kvp.Key;
  726. }
  727. else
  728. {
  729. outFieldStr += "," + kvp.Key;
  730. }
  731. }
  732. return outFieldStr;
  733. }
  734. /// <summary>
  735. /// 生成Order语句
  736. /// </summary>
  737. /// <param name="orgOrderFields"></param>
  738. /// <param name="preOrderStr"></param>
  739. /// <returns></returns>
  740. private static string BuildOrderFields(Dictionary<string, string> orgOrderFields, string preOrderStr)
  741. {
  742. string outOrderStr = string.Empty;
  743. Dictionary<string, string> outOrderFields = new Dictionary<string, string>();
  744. if (!string.IsNullOrEmpty(preOrderStr))
  745. {
  746. string[] fields = preOrderStr.Split(',');
  747. foreach (string field in fields)
  748. {
  749. string key = field.Trim().ToLower();
  750. string[] arr = key.Split(' ');
  751. if (arr.Length > 1)
  752. {
  753. key = arr[0];
  754. string sort = arr[arr.Length - 1];
  755. if (orgOrderFields.ContainsKey(key) && !outOrderFields.ContainsKey(key) && (sort == "asc" || sort == "desc"))
  756. {
  757. outOrderFields[key] = orgOrderFields[key] + " " + sort;
  758. }
  759. }
  760. else
  761. {
  762. if (orgOrderFields.ContainsKey(key) && !outOrderFields.ContainsKey(key))
  763. {
  764. outOrderFields[key] = orgOrderFields[key];
  765. }
  766. }
  767. }
  768. }
  769. foreach (KeyValuePair<string, string> kvp in outOrderFields)
  770. {
  771. if (string.IsNullOrEmpty(outOrderStr))
  772. {
  773. outOrderStr = kvp.Value;
  774. }
  775. else
  776. {
  777. outOrderStr += "," + kvp.Value;
  778. }
  779. }
  780. return outOrderStr;
  781. }
  782. /// <summary>
  783. /// 生成SELECT语句
  784. /// </summary>
  785. /// <param name="orgFields"></param>
  786. /// <param name="preOutFieldStr"></param>
  787. /// <returns></returns>
  788. private static string BuildSelectFields(Dictionary<string, string> orgFields, string preOutFieldStr)
  789. {
  790. string outFieldStr = string.Empty;
  791. Dictionary<string, string> outFields = new Dictionary<string, string>();
  792. if (!string.IsNullOrEmpty(preOutFieldStr))
  793. {
  794. string[] fields = preOutFieldStr.Split(',');
  795. foreach (string field in fields)
  796. {
  797. string key = field.Trim().ToLower();
  798. if (orgFields.ContainsKey(key) && !outFields.ContainsKey(key))
  799. {
  800. outFields[key] = orgFields[key];
  801. }
  802. }
  803. }
  804. if (outFields.Count == 0)
  805. {
  806. outFields = orgFields;
  807. }
  808. foreach (KeyValuePair<string, string> kvp in outFields)
  809. {
  810. if (string.IsNullOrEmpty(outFieldStr))
  811. {
  812. outFieldStr = kvp.Value;
  813. }
  814. else
  815. {
  816. outFieldStr += "," + kvp.Value;
  817. }
  818. }
  819. return outFieldStr;
  820. }
  821. private static void AnalyseFields(string orgFieldStr, Dictionary<string, string> orgFields, Dictionary<string, string> orgOrderFields)
  822. {
  823. string[] selectFieldArr = SplitFields(orgFieldStr);
  824. string[] pattens = new string[] { @"^\s*(?<sort>(?<key>\w+))\s*=.+$", @"^.+\s+as\s+(?<sort>(?<key>\w+))\s*$", @"^.+\s+(?<sort>(?<key>\w+))\s*$", @"^(?<sort>.*\.\s*(?<key>\w+)\s*)$", @"^\s*(?<sort>(?<key>\w+))\s*$" };
  825. foreach (string orgField in selectFieldArr)
  826. {
  827. foreach (string patten in pattens)
  828. {
  829. Match fiMatch = Regex.Match(orgField, patten, RegexOptions.IgnoreCase | RegexOptions.Singleline);
  830. if (fiMatch.Success)
  831. {
  832. string key = fiMatch.Groups["key"].Value.Trim().ToLower();
  833. if (!orgFields.ContainsKey(key))
  834. {
  835. orgFields[key] = fiMatch.Value.Trim();
  836. orgOrderFields[key] = fiMatch.Groups["sort"].Value.Trim();
  837. }
  838. break;
  839. }
  840. }
  841. }
  842. }
  843. private static string[] SplitFields(string orgFieldStr)
  844. {
  845. List<string> rslt = new List<string>();
  846. string builder = string.Empty;
  847. Stack<char> states = new Stack<char>();
  848. for (int i = 0; i < orgFieldStr.Length; i++)
  849. {
  850. char cur = orgFieldStr[i];
  851. if (states.Count == 0)
  852. {
  853. if (cur == ',')
  854. {
  855. rslt.Add(builder);
  856. builder = string.Empty;
  857. }
  858. else
  859. {
  860. builder += cur;
  861. if (cur == '(' || cur == '\'')
  862. {
  863. states.Push(cur);
  864. }
  865. }
  866. }
  867. else
  868. {
  869. builder += cur;
  870. char curstate = states.Peek();
  871. if (curstate == '\'')
  872. {
  873. if (cur == '\'')
  874. {
  875. states.Pop();
  876. }
  877. }
  878. else
  879. {
  880. if (cur == '(' || cur == '\'')
  881. {
  882. states.Push(cur);
  883. }
  884. else if (cur == ')')
  885. {
  886. states.Pop();
  887. }
  888. }
  889. }
  890. }
  891. rslt.Add(builder);
  892. return rslt.ToArray();
  893. }
  894. private static void PrepareSelectCmd(SqlCommand cmd, string strcmd, string wherestr, IEnumerable<SqlParameter> parms, ref string fields, string orderfields, int pageindex, int pagesize)
  895. {
  896. MakeSelectCmd(cmd, strcmd, ref fields, wherestr, orderfields, pageindex, pagesize, parms);
  897. }
  898. public static void SelectJoin<T>(SqlCommand cmd, string selectStr, string whereStr, IEnumerable<SqlParameter> parms, string orderByStr, string outputFields, int pageindex, int pagesize, List<T> returnList) where T : new()
  899. {
  900. PrepareSelectCmd(cmd, selectStr, whereStr, parms, ref outputFields, orderByStr, pageindex, pagesize);
  901. IList<PropertyInfo> properties = GetProperties(typeof(T), outputFields);
  902. using (SqlDataReader reader = cmd.ExecuteReader())
  903. {
  904. while (reader.Read())
  905. {
  906. T modle = new T();
  907. foreach (PropertyInfo property in properties)
  908. {
  909. MethodInfo setMethod = property.GetSetMethod();
  910. if (setMethod == null)
  911. {
  912. continue;
  913. }
  914. object value = null;
  915. try
  916. {
  917. value = reader[property.Name];
  918. }
  919. catch (Exception)
  920. {
  921. continue;
  922. }
  923. if (value == null || value == DBNull.Value)
  924. {
  925. continue;
  926. }
  927. if (value is string)
  928. {
  929. value = value.ToString().Trim();
  930. }
  931. var parmType = setMethod.GetParameters()[0].ParameterType;
  932. value = ConvertValue(parmType, value);
  933. setMethod.Invoke(modle, new object[] { value });
  934. }
  935. returnList.Add(modle);
  936. }
  937. }
  938. }
  939. private static object ConvertValue(Type parmType, object value)
  940. {
  941. if (!parmType.IsAssignableFrom(value.GetType()))
  942. {
  943. if (parmType.IsAssignableFrom(typeof(byte)))
  944. {
  945. value = Convert.ToByte(value);
  946. }
  947. else if (parmType.IsAssignableFrom(typeof(sbyte)))
  948. {
  949. value = Convert.ToSByte(value);
  950. }
  951. else if (parmType.IsAssignableFrom(typeof(short)))
  952. {
  953. value = Convert.ToInt16(value);
  954. }
  955. else if (parmType.IsAssignableFrom(typeof(ushort)))
  956. {
  957. value = Convert.ToUInt16(value);
  958. }
  959. else if (parmType.IsAssignableFrom(typeof(int)))
  960. {
  961. value = Convert.ToInt32(value);
  962. }
  963. else if (parmType.IsAssignableFrom(typeof(uint)))
  964. {
  965. value = Convert.ToUInt32(value);
  966. }
  967. else if (parmType.IsAssignableFrom(typeof(long)))
  968. {
  969. value = Convert.ToInt64(value);
  970. }
  971. else if (parmType.IsAssignableFrom(typeof(ulong)))
  972. {
  973. value = Convert.ToUInt64(value);
  974. }
  975. else if (parmType.IsAssignableFrom(typeof(float)))
  976. {
  977. value = Convert.ToSingle(value);
  978. }
  979. else if (parmType.IsAssignableFrom(typeof(double)))
  980. {
  981. value = Convert.ToDouble(value);
  982. }
  983. else if (parmType.IsAssignableFrom(typeof(decimal)))
  984. {
  985. value = Convert.ToDecimal(value);
  986. }
  987. else if (parmType.IsAssignableFrom(typeof(bool)))
  988. {
  989. value = Convert.ToBoolean(value);
  990. }
  991. else if (parmType.IsAssignableFrom(typeof(bool)))
  992. {
  993. value = Convert.ToBoolean(value);
  994. }
  995. else if (parmType.IsAssignableFrom(typeof(char)))
  996. {
  997. value = Convert.ToChar(value);
  998. }
  999. else if (parmType.IsAssignableFrom(typeof(DateTime)))
  1000. {
  1001. value = Convert.ToDateTime(value);
  1002. }
  1003. else if (parmType.IsAssignableFrom(typeof(string)))
  1004. {
  1005. value = Convert.ToString(value);
  1006. }
  1007. else
  1008. {
  1009. throw new Exception(string.Format("不能将{0}转换成{1}", value.GetType(), parmType));
  1010. }
  1011. }
  1012. return value;
  1013. }
  1014. private static IList<PropertyInfo> GetProperties(Type type, string outputFields)
  1015. {
  1016. List<PropertyInfo> rslt = new List<PropertyInfo>();
  1017. Dictionary<string, PropertyInfo> properties = GetProperties(type);
  1018. string[] fields = outputFields.Split(',');
  1019. foreach (string field in fields)
  1020. {
  1021. string key = field.Trim().ToLower();
  1022. if (properties.ContainsKey(key))
  1023. {
  1024. rslt.Add(properties[key]);
  1025. }
  1026. }
  1027. return rslt;
  1028. }
  1029. private static Dictionary<Type, Dictionary<string, PropertyInfo>> _typeinfoCache = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
  1030. private static object _syncRoot_typeinfoCache = new object();
  1031. private static Dictionary<string, PropertyInfo> GetProperties(Type type)
  1032. {
  1033. lock (_syncRoot_typeinfoCache)
  1034. {
  1035. if (_typeinfoCache.ContainsKey(type))
  1036. {
  1037. return _typeinfoCache[type];
  1038. }
  1039. PropertyInfo[] properties = type.GetProperties();
  1040. Dictionary<string, PropertyInfo> dirProperties = new Dictionary<string, PropertyInfo>();
  1041. foreach (PropertyInfo property in properties)
  1042. {
  1043. string key = property.Name.Trim().ToLower();
  1044. if (!dirProperties.ContainsKey(key) && property.GetGetMethod() != null && property.GetSetMethod() != null)
  1045. {
  1046. dirProperties[key] = property;
  1047. }
  1048. }
  1049. _typeinfoCache[type] = dirProperties;
  1050. return dirProperties;
  1051. }
  1052. }
  1053. public sealed class SqlParameterCollection : List<SqlParameter>
  1054. {
  1055. public SqlParameterCollection() { }
  1056. public SqlParameter Add(string parameterName, SqlDbType sqlDbType)
  1057. {
  1058. var rslt = new SqlParameter(parameterName, sqlDbType);
  1059. base.Add(rslt);
  1060. return rslt;
  1061. }
  1062. }
  1063. }
  1064. }