/projects/PigeonCms.Core/Helpers/Database.cs

http://pigeoncms.googlecode.com/ · C# · 720 lines · 474 code · 64 blank · 182 comment · 50 complexity · d3ce9fe66fc52d73dcbc1ebacb00a676 MD5 · raw file

  1. using System;
  2. using System.Configuration;
  3. using System.Data;
  4. using System.Text;
  5. using System.Web;
  6. using System.Web.Security;
  7. using System.Web.UI;
  8. using System.Web.UI.HtmlControls;
  9. using System.Web.UI.WebControls;
  10. using System.Web.UI.WebControls.WebParts;
  11. using System.Collections.Generic;
  12. using System.ComponentModel;
  13. using System.Data.Common;
  14. using System.Reflection;
  15. using System.Diagnostics;
  16. using System.IO;
  17. namespace PigeonCms
  18. {
  19. /// <summary>
  20. /// Database useful functions
  21. /// </summary>
  22. public static class Database
  23. {
  24. /// <summary>
  25. /// retrieve the connectionstring using ConnectionStringName setting in AppSettings section
  26. /// </summary>
  27. public static string ConnString
  28. {
  29. get
  30. {
  31. try
  32. {
  33. string res = "";
  34. string connectionStringName = ConfigurationManager.AppSettings["ConnectionStringName"].ToString();
  35. ConnectionStringsSection section = (ConnectionStringsSection)ConfigurationManager.GetSection("connectionStrings");
  36. res = section.ConnectionStrings[connectionStringName].ToString();
  37. return res;
  38. }
  39. catch (Exception ex1)
  40. {
  41. throw new Exception("Invalid connectionStringName", ex1);
  42. }
  43. }
  44. }
  45. public static string ProviderName
  46. {
  47. get { return ConfigurationManager.AppSettings["ProviderName"].ToString(); }
  48. }
  49. public static DbProviderFactory ProviderFactory
  50. {
  51. get
  52. {
  53. return DbProviderFactories.GetFactory(Database.ProviderName);
  54. }
  55. }
  56. public enum MoveRecordDirection
  57. {
  58. Up = 1,
  59. Down
  60. }
  61. /// <summary>
  62. /// parse sql string before the command execution
  63. /// </summary>
  64. /// <param name="sqlQuery"></param>
  65. /// <param name="tabPrefix">current installation tab prefix (usually 'pgn_')</param>
  66. /// <returns></returns>
  67. public static string ParseSql(string sqlQuery, string tabPrefix)
  68. {
  69. const string PlaceHolder = "#__";
  70. if (!string.IsNullOrEmpty(tabPrefix))
  71. return sqlQuery.Replace(PlaceHolder, tabPrefix);
  72. else
  73. return sqlQuery.Replace(PlaceHolder, Config.TabPrefix);
  74. }
  75. /// <summary>
  76. /// parse sql string before the command execution
  77. /// </summary>
  78. /// <param name="sqlQuery"></param>
  79. /// <returns></returns>
  80. public static string ParseSql(string sqlQuery)
  81. {
  82. return ParseSql(sqlQuery, "");
  83. }
  84. public static string AddDatesRangeParameters(DbParameterCollection parameters,
  85. DbProviderFactory myProv, string sqlFieldName, DatesRange rangeFilter)
  86. {
  87. string res = "";
  88. if (rangeFilter.DateRangeType == DatesRange.RangeType.Always)
  89. res = "1=1";
  90. else if (rangeFilter.DateRangeType == DatesRange.RangeType.None)
  91. res = "1=0";
  92. else
  93. {
  94. res = "1=1";
  95. if (rangeFilter.InitDate != DateTime.MinValue)
  96. {
  97. res += " AND " + sqlFieldName + " >= @InitDate";
  98. parameters.Add(Database.Parameter(myProv, "InitDate", rangeFilter.InitDate));
  99. }
  100. if (rangeFilter.EndDate != DateTime.MaxValue)
  101. {
  102. res += " AND " + sqlFieldName + " < @EndDate";
  103. parameters.Add(Database.Parameter(myProv, "EndDate", rangeFilter.EndDate.AddDays(1)));
  104. }
  105. }
  106. return res;
  107. }
  108. /// <summary>
  109. /// execute 1 sql statement
  110. /// </summary>
  111. /// <param name="myRd"></param>
  112. /// <param name="myCmd"></param>
  113. /// <param name="sqlCommand">sql string (already parsed) with Database.ParseSql method</param>
  114. /// <returns>formatted results</returns>
  115. public static string ExecuteCommand(DbDataReader myRd, DbCommand myCmd, string sqlCommand)
  116. {
  117. string res = "";
  118. myCmd.CommandText = sqlCommand;
  119. myRd = myCmd.ExecuteReader();
  120. if (myRd.HasRows)
  121. {
  122. int row = 0;
  123. res += "<table>";
  124. while (myRd.Read())
  125. {
  126. //col headers
  127. if (row == 0)
  128. {
  129. res += "<tr>";
  130. for (int i = 0; i < myRd.FieldCount; i++)
  131. {
  132. res += "<th>" + myRd.GetName(i) + "</th>";
  133. }
  134. res += "</tr>";
  135. }
  136. res += "<tr>";
  137. for (int i = 0; i < myRd.FieldCount; i++)
  138. {
  139. res += "<td>" +
  140. HttpContext.Current.Server.HtmlEncode(myRd[i].ToString()) +
  141. "</td>";
  142. }
  143. res += "</tr>";
  144. row++;
  145. }
  146. res += "</table>";
  147. }
  148. myRd.Close();
  149. return res;
  150. }
  151. /// <summary>
  152. /// execute multiple sql statement
  153. /// </summary>
  154. /// <param name="myRd"></param>
  155. /// <param name="myCmd"></param>
  156. /// <param name="sqlQuery">sql string (already parsed) with Database.ParseSql method</param>
  157. /// <returns></returns>
  158. public static string ExecuteQuery(DbDataReader myRd, DbCommand myCmd, string sqlQuery)
  159. {
  160. string line = ""; //current sqlQuery line
  161. string sqlCommand = ""; //single command statement
  162. int lineCounter = 0;
  163. string res = "";
  164. try
  165. {
  166. StringReader reader = new StringReader(sqlQuery);
  167. while ((line = reader.ReadLine()) != null)
  168. {
  169. lineCounter++;
  170. line = line.Trim();
  171. if (line.ToUpper() == "GO")
  172. {
  173. res += Database.ExecuteCommand(myRd, myCmd, sqlCommand);
  174. sqlCommand = "";
  175. }
  176. else
  177. {
  178. sqlCommand += line + "\n";
  179. }
  180. }
  181. if (!string.IsNullOrEmpty(sqlCommand))
  182. res += Database.ExecuteCommand(myRd, myCmd, sqlCommand);
  183. }
  184. catch (DbException ex)
  185. {
  186. throw new Exception(@"Sql query line " + lineCounter, ex);
  187. }
  188. return res;
  189. }
  190. public static DbParameter Parameter(DbProviderFactory provider, string paramName, object paramValue)
  191. {
  192. return Parameter(provider, paramName, paramValue, DbType.Object);
  193. }
  194. public static DbParameter Parameter(DbProviderFactory provider, string paramName, object paramValue, DbType paramType)
  195. {
  196. DbParameter p1 = provider.CreateParameter();
  197. p1.ParameterName = paramName;
  198. p1.Value = paramValue;
  199. if (paramType != DbType.Object)
  200. {
  201. p1.DbType = paramType;
  202. }
  203. //p1.Direction = ParameterDirection.Input
  204. return p1;
  205. }
  206. }
  207. public class TableManagerWithOrdering<T,F,Kkey>:
  208. PigeonCms.TableManager<T,F,Kkey> where T: PigeonCms.ITableWithOrdering
  209. {
  210. /// <summary>
  211. /// change record order in list
  212. /// </summary>
  213. /// <param name="recordId">current record id</param>
  214. /// <param name="direction">direction up, down</param>
  215. [DataObjectMethod(DataObjectMethodType.Update, false)]
  216. public virtual void MoveRecord(Kkey recordId, Database.MoveRecordDirection direction)
  217. {
  218. T o1;// = new T();
  219. T o2;// = new T();
  220. int tmpOrdering = 0;
  221. try
  222. {
  223. o1 = GetByKey(recordId);
  224. tmpOrdering = o1.Ordering;
  225. if (direction == Database.MoveRecordDirection.Up)
  226. {
  227. o2 = GetByKey(GetPreviousRecordInOrder(tmpOrdering, recordId));
  228. }
  229. else
  230. {
  231. o2 = GetByKey(GetNextRecordInOrder(tmpOrdering, recordId));
  232. if (o1.Ordering == o2.Ordering) o2.Ordering++;
  233. }
  234. if (o2.Ordering != tmpOrdering)
  235. {
  236. o1.Ordering = o2.Ordering;
  237. o2.Ordering = tmpOrdering;
  238. Update(o1);
  239. Update(o2);
  240. }
  241. }
  242. finally
  243. {
  244. }
  245. }
  246. /// <summary>
  247. /// return previous record id in order, if first return currentRecordId
  248. /// </summary>
  249. /// <param name="orderId"></param>
  250. /// <param name="currentRecordId"></param>
  251. /// <returns>a record id</returns>
  252. protected virtual Kkey GetPreviousRecordInOrder(int ordering, Kkey currentRecordId)
  253. {
  254. DbProviderFactory myProv = Database.ProviderFactory;
  255. DbConnection myConn = myProv.CreateConnection();
  256. DbDataReader myRd = null;
  257. DbCommand myCmd = myConn.CreateCommand();
  258. string sSql;
  259. Kkey result = currentRecordId;
  260. try
  261. {
  262. myConn.ConnectionString = Database.ConnString;
  263. myConn.Open();
  264. myCmd.Connection = myConn;
  265. sSql = "SELECT TOP 1 [" + this.KeyFieldName + "] FROM [" + this.TableName + "] WHERE ordering < @ordering ORDER BY ordering DESC ";
  266. myCmd.CommandText = Database.ParseSql(sSql);
  267. myCmd.Parameters.Add(Database.Parameter(myProv, "ordering", ordering));
  268. myRd = myCmd.ExecuteReader();
  269. if (myRd.Read())
  270. {
  271. if (myRd[0] != DBNull.Value)
  272. {
  273. result = (Kkey)myRd[0];
  274. }
  275. }
  276. myRd.Close();
  277. //se nn trovo un record prendo quello precedente per chiave (per init tabella)
  278. if (result.ToString() == "0")
  279. {
  280. sSql = "SELECT TOP 1 [" + KeyFieldName + "] FROM " + TableName
  281. + " WHERE [" + KeyFieldName + "] < @currentRecordId ORDER BY ordering ASC ";
  282. myCmd.CommandText = Database.ParseSql(sSql);
  283. myCmd.Parameters.Add(Database.Parameter(myProv, "currentRecordId", currentRecordId));
  284. myRd = myCmd.ExecuteReader();
  285. if (myRd.Read())
  286. {
  287. if (myRd[0] != DBNull.Value)
  288. {
  289. result = (Kkey)myRd[0];
  290. }
  291. }
  292. myRd.Close();
  293. }
  294. }
  295. finally
  296. {
  297. myConn.Dispose();
  298. }
  299. return result;
  300. }
  301. /// <summary>
  302. /// return next record in order, if last return currentRecordId
  303. /// </summary>
  304. /// <param name="orderId"></param>
  305. /// <param name="currentRecordId"></param>
  306. /// <returns>a recordId</returns>
  307. protected virtual Kkey GetNextRecordInOrder(int ordering, Kkey currentRecordId)
  308. {
  309. DbProviderFactory myProv = Database.ProviderFactory;
  310. DbConnection myConn = myProv.CreateConnection();
  311. DbDataReader myRd = null;
  312. DbCommand myCmd = myConn.CreateCommand();
  313. string sSql;
  314. Kkey result = currentRecordId;
  315. try
  316. {
  317. myConn.ConnectionString = Database.ConnString;
  318. myConn.Open();
  319. myCmd.Connection = myConn;
  320. sSql = "SELECT TOP 1 [" + this.KeyFieldName + "] FROM [" + this.TableName + "] WHERE ordering > @ordering ORDER BY ordering ASC ";
  321. myCmd.CommandText = Database.ParseSql(sSql);
  322. myCmd.Parameters.Add(Database.Parameter(myProv, "ordering", ordering));
  323. myRd = myCmd.ExecuteReader();
  324. if (myRd.Read())
  325. {
  326. if (myRd[0] != DBNull.Value)
  327. {
  328. result = (Kkey)myRd[0];
  329. }
  330. }
  331. myRd.Close();
  332. //se nn trovo un record prendo quello successivo per chiave (per init tabella)
  333. if (result.ToString() == currentRecordId.ToString())
  334. {
  335. sSql = "SELECT TOP 1 [" + KeyFieldName + "] FROM " + TableName
  336. + " WHERE [" + KeyFieldName + "] > @currentRecordId ORDER BY ordering, [" + KeyFieldName + "] ";
  337. myCmd.CommandText = Database.ParseSql(sSql);
  338. myCmd.Parameters.Add(Database.Parameter(myProv, "currentRecordId", currentRecordId));
  339. myRd = myCmd.ExecuteReader();
  340. if (myRd.Read())
  341. {
  342. if (myRd[0] != DBNull.Value)
  343. {
  344. result = (Kkey)myRd[0];
  345. }
  346. }
  347. myRd.Close();
  348. }
  349. }
  350. finally
  351. {
  352. myConn.Dispose();
  353. }
  354. return result;
  355. }
  356. }
  357. /// <summary>
  358. /// common methods in DAL class
  359. /// </summary>
  360. /// <typeparam name="T">BLL class</typeparam>
  361. /// <typeparam name="F">BLL filter class</typeparam>
  362. /// <typeparam name="K">type of key class</typeparam>
  363. [DataObject()]
  364. public class TableManager<T,F,Kkey> where T: PigeonCms.ITable
  365. {
  366. #region fields
  367. private string tableName = "";
  368. private string keyFieldName = "";
  369. /// <summary>
  370. /// name of the key field in the table
  371. /// </summary>
  372. public string KeyFieldName
  373. {
  374. [DebuggerStepThrough()]
  375. get { return this.keyFieldName; }
  376. [DebuggerStepThrough()]
  377. set { this.keyFieldName = value; }
  378. }
  379. /// <summary>
  380. /// name of the table managed by the class
  381. /// </summary>
  382. public string TableName
  383. {
  384. [DebuggerStepThrough()]
  385. get { return this.tableName; }
  386. [DebuggerStepThrough()]
  387. set { this.tableName = value; }
  388. }
  389. #endregion
  390. [DebuggerStepThrough()]
  391. public TableManager(){}
  392. [DebuggerStepThrough()]
  393. public TableManager(string mainTableName, string keyFieldName)
  394. {
  395. TableName = mainTableName;
  396. KeyFieldName = keyFieldName;
  397. }
  398. /// <summary>
  399. /// dictionary list to use in module admin area (combo)
  400. /// </summary>
  401. /// <returns></returns>
  402. [DataObjectMethod(DataObjectMethodType.Select, false)]
  403. public virtual Dictionary<string, string> GetList()
  404. {
  405. int counter = 0;
  406. Dictionary<string, string> res = new Dictionary<string, string>();
  407. F filter = default(F); //= new F();
  408. List<T> list = GetByFilter(filter, "");
  409. foreach (T item in list)
  410. {
  411. res.Add(counter.ToString(), item.ToString());
  412. }
  413. return res;
  414. }
  415. [DataObjectMethod(DataObjectMethodType.Select, true)]
  416. public virtual List<T> GetByFilter(F filter, string sort)
  417. {
  418. throw new NotImplementedException(); //to complete
  419. //Type t = typeof(F);
  420. //PropertyInfo[] props = t.GetProperties();
  421. //DbProviderFactory myProv = Database.ProviderFactory;
  422. //DbConnection myConn = myProv.CreateConnection();
  423. //DbDataReader myRd = null;
  424. //DbCommand myCmd = myConn.CreateCommand();
  425. //string sSql;
  426. //List<T> result = new List<T>();
  427. //try
  428. //{
  429. // myConn.ConnectionString = Database.ConnString;
  430. // myConn.Open();
  431. // myCmd.Connection = myConn;
  432. // sSql = "SELECT [" + this.KeyFieldName + "] FROM [" + this.TableName + "] t "
  433. // + " WHERE [" + this.KeyFieldName + "] > 0 ";
  434. // foreach (PropertyInfo prop in props)
  435. // {
  436. // DataObjectFieldAttribute[] attrs = (DataObjectFieldAttribute[])prop.GetCustomAttributes(typeof(DataObjectFieldAttribute), true);
  437. // if (attrs.Length > 0)
  438. // {
  439. // //switch (attrs[0].GetType().)
  440. // //{
  441. // // case Type.
  442. // // default:
  443. // //}
  444. // if (attrs[0].PrimaryKey)
  445. // {
  446. // if ((int)prop.GetValue(filter, null) > 0 || (int)prop.GetValue(filter, null) == -1)
  447. // {
  448. // sSql += " AND ["+ prop.Name +"] = @RecordId ";
  449. // myCmd.Parameters.Add(Database.Parameter(myProv, "RecordId", (int)prop.GetValue(filter, null)));
  450. // }
  451. // }
  452. // }
  453. // //if (!string.IsNullOrEmpty(filter.Nome))
  454. // //{
  455. // // sSql += " AND t.Nome = @Nome ";
  456. // // myCmd.Parameters.Add(Database.Parameter(myProv, "Nome", filter.Nome));
  457. // //}
  458. // //if (filter.Visible != Utility.TristateBool.NotSet)
  459. // //{
  460. // // sSql += " AND t.Visible = @Visible ";
  461. // // myCmd.Parameters.Add(Database.Parameter(myProv, "Visible", filter.Visible));
  462. // //}
  463. // }
  464. // if (!string.IsNullOrEmpty(sort))
  465. // {
  466. // sSql += " ORDER BY " + sort;
  467. // }
  468. // else
  469. // {
  470. // sSql += " ORDER BY OrderId ";
  471. // }
  472. // myCmd.CommandText = Database.ParseSql(sSql);
  473. // myRd = myCmd.ExecuteReader();
  474. // while (myRd.Read())
  475. // {
  476. // T item = GetById((Kkey)myRd[this.KeyFieldName]);
  477. // result.Add(item);
  478. // }
  479. // myRd.Close();
  480. //}
  481. //finally
  482. //{
  483. // myConn.Dispose();
  484. //}
  485. //return result;
  486. }
  487. [DataObjectMethod(DataObjectMethodType.Select, false)]
  488. public virtual T GetByKey(Kkey id)
  489. {
  490. throw new NotImplementedException();
  491. }
  492. /// <summary>
  493. /// update the existing record
  494. /// </summary>
  495. /// <param name="theObj">The obj to update</param>
  496. /// <returns>number of records affected</returns>
  497. [DataObjectMethod(DataObjectMethodType.Update, false)]
  498. public virtual int Update(T theObj)
  499. {
  500. throw new NotImplementedException();
  501. }
  502. /// <summary>
  503. /// Insert a new record; newObj.recordId=last+1, newObj.OrderId=last+1
  504. /// </summary>
  505. /// <param name="newObj">Data about the new object</param>
  506. /// <returns>The new obj</returns>
  507. [DataObjectMethod(DataObjectMethodType.Insert, false)]
  508. public virtual T Insert(T newObj)
  509. {
  510. throw new NotImplementedException();
  511. }
  512. /// <summary>
  513. /// Delete a record from its own table
  514. /// </summary>
  515. /// <param name="recordId">P Key of the record to delete</param>
  516. /// <returns>Num of records deleted</returns>
  517. [DataObjectMethod(DataObjectMethodType.Delete, true)]
  518. public virtual int DeleteById(Kkey recordId)
  519. {
  520. if (string.IsNullOrEmpty(TableName) || string.IsNullOrEmpty(KeyFieldName))
  521. throw new NotImplementedException("Not implemented or TableName/KeyFieldName not filled");
  522. DbProviderFactory myProv = Database.ProviderFactory;
  523. DbConnection myConn = myProv.CreateConnection();
  524. DbCommand myCmd = myConn.CreateCommand();
  525. string sSql;
  526. int res = 0;
  527. try
  528. {
  529. myConn.ConnectionString = Database.ConnString;
  530. myConn.Open();
  531. myCmd.Connection = myConn;
  532. sSql = "DELETE FROM [" + this.TableName + "] WHERE [" + this.KeyFieldName + "] = @recordId ";
  533. myCmd.CommandText = Database.ParseSql(sSql);
  534. myCmd.Parameters.Add(Database.Parameter(myProv, "recordId", recordId));
  535. res = myCmd.ExecuteNonQuery();
  536. }
  537. finally
  538. {
  539. myConn.Dispose();
  540. }
  541. return res;
  542. }
  543. /// <summary>
  544. /// fill the obj2Fill with data in myRd
  545. /// </summary>
  546. /// <param name="obj2Fill"></param>
  547. /// <param name="myRd"></param>
  548. protected virtual void FillObject(T obj2Fill, DbDataReader myRd)
  549. {
  550. throw new NotImplementedException();
  551. }
  552. /// <summary>
  553. /// Used during Insert method. Put the new record in the last order position
  554. /// </summary>
  555. /// <returns>The order position</returns>
  556. protected virtual int GetNextOrderId()
  557. {
  558. return GetNextProgressive(this.TableName, "orderId");
  559. }
  560. /// <summary>
  561. /// Used during Insert method. Put the new record in the last order position
  562. /// </summary>
  563. /// <returns>The order position</returns>
  564. protected virtual int GetNextOrdering()
  565. {
  566. return GetNextProgressive(this.TableName, "ordering");
  567. }
  568. /// <summary>
  569. /// Give the new record id for current class,key T,F
  570. /// </summary>
  571. /// <returns>The new record Id</returns>
  572. protected virtual int GetNextId()
  573. {
  574. return GetNextProgressive(this.TableName, this.KeyFieldName);
  575. }
  576. /// <summary>
  577. /// Give the new record id for current class,key T,F
  578. /// </summary>
  579. /// <returns>The next progressive value</returns>
  580. protected int GetNextProgressive(string tableName, string fieldName)
  581. {
  582. DbProviderFactory myProv = Database.ProviderFactory;
  583. DbConnection myConn = myProv.CreateConnection();
  584. DbDataReader myRd = null;
  585. DbCommand myCmd = myConn.CreateCommand();
  586. string sSql;
  587. int result = 0;
  588. try
  589. {
  590. myConn.ConnectionString = Database.ConnString;
  591. myConn.Open();
  592. myCmd.Connection = myConn;
  593. sSql = "SELECT max([" + fieldName + "]) FROM [" + tableName + "]";
  594. myCmd.CommandText = Database.ParseSql(sSql);
  595. myRd = myCmd.ExecuteReader();
  596. if (myRd.Read())
  597. {
  598. if (myRd[0] != DBNull.Value)
  599. {
  600. result = (int)myRd[0];
  601. }
  602. }
  603. myRd.Close();
  604. result++;
  605. }
  606. finally
  607. {
  608. myConn.Dispose();
  609. }
  610. return result;
  611. }
  612. }
  613. /// <summary>
  614. /// Generic Table used to implement a BLL object
  615. /// </summary>
  616. public interface ITable
  617. {
  618. }
  619. public interface ITableWithOrdering: ITable
  620. {
  621. int Ordering { get; set; }
  622. }
  623. public interface ITableWithComments : ITable
  624. {
  625. int CommentsGroupId { get; set; }
  626. }
  627. public interface ITableWithPermissions : ITable
  628. {
  629. //read
  630. MenuAccesstype ReadAccessType { get; set; }
  631. int ReadPermissionId { get; set; }
  632. List<string> ReadRolenames { get; set; }
  633. string ReadAccessCode { get; set; }
  634. int ReadAccessLevel { get; set; }
  635. //write
  636. MenuAccesstype WriteAccessType { get; set; }
  637. int WritePermissionId { get; set; }
  638. List<string> WriteRolenames { get; set; }
  639. string WriteAccessCode { get; set; }
  640. int WriteAccessLevel { get; set; }
  641. }
  642. public interface ITableManager
  643. {
  644. //*** not implemented
  645. //int DeleteById(int recordId);
  646. //int Update(ITableObject theObj);
  647. //ITableObject Insert(ITableObject newObj);
  648. //List<ITableObject> GetByFilter();
  649. //ITableObject GetById();
  650. }
  651. public interface ITableManagerWithPermission: ITable
  652. {
  653. bool CheckUserContext { get; }
  654. bool WriteMode { get; }
  655. }
  656. }