/Source/HydroDesktop.Data/Database/MetadataCacheManagerSQL.cs

# · C# · 1174 lines · 836 code · 147 blank · 191 comment · 76 complexity · 724921c975c448f5e08497c48fd47195 MD5 · raw file

Large files are truncated click here to view the full file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using HydroDesktop.Interfaces;
  6. using HydroDesktop.Interfaces.ObjectModel;
  7. using System.Data;
  8. using System.Data.Common;
  9. using System.Globalization;
  10. namespace HydroDesktop.Database
  11. {
  12. /// <summary>
  13. /// This class is responsible for communication with the 'Metadata Cache' database
  14. /// This is an alternative implementation internally using SQL queries instead of NHibernate.
  15. /// This is to compare saving speed.
  16. /// </summary>
  17. public class MetadataCacheManagerSQL
  18. {
  19. #region Variables
  20. //helper class which communicates with the database
  21. private DbOperations _db;
  22. // lookup caches used by the SaveSeries method
  23. private Dictionary<string, Site> _siteCache = new Dictionary<string, Site> ();
  24. private Dictionary<string, Variable> _variableCache = new Dictionary<string, Variable> ();
  25. private Dictionary<string, Method> _methodCache = new Dictionary<string, Method> ();
  26. private Dictionary<string, QualityControlLevel> _qualControlCache = new Dictionary<string, QualityControlLevel> ();
  27. private Dictionary<string, Source> _sourcesCache = new Dictionary<string, Source> ();
  28. #endregion
  29. #region Constructor
  30. /// <summary>
  31. /// Creates a new instance of the manager given a connection string
  32. /// </summary>
  33. /// <param name="dbType">The type of the database (SQLite, SQLServer, ...)</param>
  34. /// <param name="connectionString">The connection string</param>
  35. public MetadataCacheManagerSQL ( DatabaseTypes dbType, string connectionString )
  36. {
  37. _db = new DbOperations(connectionString, dbType);
  38. }
  39. /// <summary>
  40. /// Creates a new instance of the manager using a DbOperations object
  41. /// </summary>
  42. /// <param name="db">The dbOperations object</param>
  43. public MetadataCacheManagerSQL(DbOperations db)
  44. {
  45. _db = db;
  46. }
  47. #endregion
  48. private bool NumberIsBetween ( double numberToCheck, double bounds1, double bounds2, bool inclusiveAtBounds )
  49. {
  50. double lowerBound, upperBound;
  51. if ( bounds1 > bounds2 )
  52. {
  53. lowerBound = bounds2;
  54. upperBound = bounds1;
  55. }
  56. else
  57. {
  58. lowerBound = bounds1;
  59. upperBound = bounds2;
  60. }
  61. if ( inclusiveAtBounds == true )
  62. {
  63. return (numberToCheck >= lowerBound && numberToCheck <= upperBound);
  64. }
  65. else
  66. {
  67. return (numberToCheck > lowerBound && numberToCheck < upperBound);
  68. }
  69. }
  70. private bool EnvelopesIntersect ( double env1xMin, double env1xMax, double env1yMin, double env1yMax, double env2xMin, double env2xMax, double env2yMin, double env2yMax )
  71. {
  72. return (((NumberIsBetween ( env1xMin, env2xMin, env2xMax, true ) || NumberIsBetween ( env1xMax, env2xMin, env2xMax, true )) && (NumberIsBetween ( env1yMin, env2yMin, env2yMax, true ) || NumberIsBetween ( env1yMax, env2yMin, env2yMax, true ))) ||
  73. ((NumberIsBetween ( env2xMin, env1xMin, env1xMax, true ) || NumberIsBetween ( env2xMax, env1xMin, env1xMax, true )) && (NumberIsBetween ( env2yMin, env1yMin, env1yMax, true ) || NumberIsBetween ( env2yMax, env1yMin, env1yMax, true ))));
  74. }
  75. private bool PointIntersectsEnvelope ( double pointX, double pointY, double envXMin, double envXMax, double envYMin, double envYMax )
  76. {
  77. return (NumberIsBetween ( pointX, envXMin, envXMax, true ) && NumberIsBetween ( pointY, envYMin, envYMax, true ));
  78. }
  79. private bool DateRangesOverlap ( DateTime startDate1, DateTime endDate1, DateTime startDate2, DateTime endDate2 )
  80. {
  81. return (((startDate1 >= startDate2) && (startDate1 <= endDate2)) ||
  82. ((endDate1 >= startDate2) && (endDate1 <= endDate2)) ||
  83. ((startDate2 >= startDate1) && (startDate2 <= endDate1)) ||
  84. ((endDate2 >= startDate1) && (endDate2 <= endDate1)));
  85. }
  86. #region Public Methods
  87. /// <summary>
  88. /// Get all data services saved in the metadata cache database
  89. /// </summary>
  90. public IList<DataServiceInfo> GetAllServices ()
  91. {
  92. string sql = "SELECT * FROM DataServices";
  93. System.Data.DataTable tbl = _db.LoadTable("services", sql);
  94. IList<DataServiceInfo> services = null;
  95. services = new List<DataServiceInfo> ();
  96. if ( tbl.Rows.Count > 0 )
  97. {
  98. foreach(System.Data.DataRow row in tbl.Rows)
  99. {
  100. services.Add(ServiceFromDataRow(row));
  101. }
  102. }
  103. return services;
  104. }
  105. /// <summary>
  106. /// Get data service by serviceUrl
  107. /// </summary>
  108. /// <param name="serviceURL">ServiceUrl</param>
  109. /// <returns>Data service or null (if not found)</returns>
  110. public DataServiceInfo GetServiceByServiceUrl(string serviceURL)
  111. {
  112. var sql = string.Format("SELECT * FROM DataServices where ServiceID = '{0}'", serviceURL);
  113. var tbl = _db.LoadTable("services", sql);
  114. return tbl.Rows.Count == 1 ? ServiceFromDataRow(tbl.Rows[0]) : null;
  115. }
  116. #endregion
  117. /// <summary>
  118. /// Gets all sites in box (not implemented)
  119. /// </summary>
  120. /// <param name="xMin">minimum x (longitude)</param>
  121. /// <param name="xMax">maximum x (lognitude)</param>
  122. /// <param name="yMin">minimum y (latitude)</param>
  123. /// <param name="yMax">maximum y (latitude)</param>
  124. public void GetSitesInBox ( double xMin, double xMax, double yMin, double yMax )
  125. {
  126. throw new System.NotImplementedException ();
  127. }
  128. /// <summary>
  129. /// Gets a list of all services within the bounding box
  130. /// </summary>
  131. /// <param name="xMin">minimum x (longitude)</param>
  132. /// <param name="xMax">maximum x (lognitude)</param>
  133. /// <param name="yMin">minimum y (latitude)</param>
  134. /// <param name="yMax">maximum y (latitude)</param>
  135. /// <returns>the list of serviceInfo objects matching the criteria</returns>
  136. public IList<DataServiceInfo> GetServicesInBox ( double xMin, double xMax, double yMin, double yMax )
  137. {
  138. //IList<DataServiceInfo> services = null;
  139. string sql = "SELECT * FROM DataServicesCache WHERE " +
  140. String.Format("EastLongitude BETWEEN {0} AND {1}", xMin, xMax) +
  141. String.Format("OR WestLongitude BETWEEN {0} AND {1}", xMin, xMax) +
  142. String.Format("OR NorthLatitude BETWEEN {0} AND {1}", yMin, yMax) +
  143. String.Format("OR SouthLatitude BETWEEN {0} AND {1}", yMin, yMax);
  144. DataTable tbl = _db.LoadTable(sql);
  145. IList<DataServiceInfo> services = null;
  146. if (tbl.Rows.Count > 0)
  147. {
  148. services = new List<DataServiceInfo>();
  149. foreach (System.Data.DataRow row in tbl.Rows)
  150. {
  151. services.Add(ServiceFromDataRow(row));
  152. }
  153. }
  154. return services;
  155. }
  156. private string DetailedSeriesSQLQuery()
  157. {
  158. string sql = "SELECT SeriesID, " +
  159. "SiteName, SiteCode, Latitude, Longitude, " +
  160. "VariableName, VariableCode, DataType, ValueType, Speciation, SampleMedium, " +
  161. "TimeSupport, GeneralCategory, " +
  162. "TimeUnitsName, " +
  163. "BeginDateTime, EndDateTime, DataSeriesCache.ValueCount, ServiceTitle, ServiceEndpointURL " +
  164. "FROM DataSeriesCache " +
  165. "LEFT JOIN SitesCache ON DataSeriesCache.SiteID = SitesCache.SiteID " +
  166. "LEFT JOIN VariablesCache ON DataSeriesCache.VariableID = VariablesCache.VariableID " +
  167. "LEFT JOIN DataServices ON DataSeriesCache.ServiceID = DataServices.ServiceID";
  168. return sql;
  169. }
  170. private DataServiceInfo ServiceFromDataRow(System.Data.DataRow row)
  171. {
  172. DataServiceInfo dsi = new DataServiceInfo();
  173. dsi.Id = DataReader.ReadInteger(row["ServiceID"]);
  174. dsi.ServiceCode = DataReader.ReadString(row["ServiceCode"]);
  175. dsi.ServiceName = DataReader.ReadString(row["ServiceName"]);
  176. dsi.ServiceType = DataReader.ReadString(row["ServiceType"]);
  177. dsi.Version = DataReader.ReadDouble(row["ServiceVersion"]);
  178. dsi.Protocol = DataReader.ReadString(row["ServiceProtocol"]);
  179. dsi.EndpointURL = DataReader.ReadString(row["ServiceEndpointURL"]);
  180. dsi.DescriptionURL = DataReader.ReadString(row["ServiceDescriptionURL"]);
  181. dsi.NorthLatitude = DataReader.ReadDouble(row["NorthLatitude"]);
  182. dsi.SouthLatitude = DataReader.ReadDouble(row["SouthLatitude"]);
  183. dsi.EastLongitude = DataReader.ReadDouble(row["EastLongitude"]);
  184. dsi.WestLongitude = DataReader.ReadDouble(row["WestLongitude"]);
  185. dsi.Abstract = DataReader.ReadString(row["Abstract"]);
  186. dsi.ContactEmail = DataReader.ReadString(row["ContactEmail"]);
  187. dsi.ContactName = DataReader.ReadString(row["ContactName"]);
  188. dsi.Citation = DataReader.ReadString(row["Citation"]);
  189. dsi.IsHarvested = DataReader.ReadBoolean(row["IsHarvested"]);
  190. dsi.HarveDateTime = DataReader.ReadDateTime(row["HarveDateTime"]);
  191. dsi.ServiceTitle = DataReader.ReadString(row["ServiceTitle"]);
  192. return dsi;
  193. }
  194. private Variable VariableFromDataRow(DataRow row)
  195. {
  196. Variable v = new Variable();
  197. v.Name = Convert.ToString(row["VariableName"]);
  198. v.Code = Convert.ToString(row["VariableCode"]);
  199. v.DataType = Convert.ToString(row["DataType"]);
  200. v.ValueType = Convert.ToString(row["ValueType"]);
  201. v.Speciation = Convert.ToString(row["Speciation"]);
  202. v.SampleMedium = Convert.ToString(row["SampleMedium"]);
  203. v.TimeSupport = Convert.ToDouble(row["TimeSupport"]);
  204. v.GeneralCategory = Convert.ToString(row["GeneralCategory"]);
  205. v.VariableUnit = Unit.Unknown;
  206. v.VariableUnit.Name = Convert.ToString(row["VariableUnitsName"]);
  207. v.VariableUnit.Abbreviation = Convert.ToString(row["VariableUnitsAbbreviation"]);
  208. v.TimeUnit = Unit.UnknownTimeUnit;
  209. v.TimeUnit.Name = Convert.ToString(row["TimeUnitsName"]);
  210. v.IsRegular = Convert.ToBoolean(row["IsRegular"]);
  211. v.NoDataValue = Convert.ToDouble(row["NoDataValue"]);
  212. v.Id = Convert.ToInt32(row["VariableID"]);
  213. return v;
  214. }
  215. private SeriesMetadata SeriesFromDataRow(DataRow row)
  216. {
  217. Site site = new Site();
  218. site.Name = Convert.ToString(row["SiteName"]);
  219. site.Code = Convert.ToString(row["SiteCode"]);
  220. site.Latitude = Convert.ToDouble(row["Latitude"]);
  221. site.Longitude = Convert.ToDouble(row["Longitude"]);
  222. Variable v = new Variable();
  223. v.Name = Convert.ToString(row["VariableName"]);
  224. v.Code = Convert.ToString(row["VariableCode"]);
  225. v.DataType = Convert.ToString(row["DataType"]);
  226. v.ValueType = Convert.ToString(row["ValueType"]);
  227. v.Speciation = Convert.ToString(row["Speciation"]);
  228. v.SampleMedium = Convert.ToString(row["SampleMedium"]);
  229. v.TimeSupport = Convert.ToDouble(row["TimeSupport"]);
  230. v.GeneralCategory = Convert.ToString(row["GeneralCategory"]);
  231. v.VariableUnit = Unit.Unknown;
  232. v.VariableUnit.Name = Convert.ToString(row["VariableUnitsName"]);
  233. v.TimeUnit = Unit.UnknownTimeUnit;
  234. v.TimeUnit.Name = Convert.ToString(row["TimeUnitsName"]);
  235. Method m = Method.Unknown;
  236. //m.Description = Convert.ToString(row["MethodDescription"]);
  237. Source src = Source.Unknown;
  238. //src.Description = Convert.ToString(row["SourceDescription"]);
  239. src.Organization = Convert.ToString(row["Organization"]);
  240. src.Citation = Convert.ToString(row["Citation"]);
  241. QualityControlLevel qc = QualityControlLevel.Unknown;
  242. //qc.Code = Convert.ToString(row["QualityControlLevelCode"]);
  243. //qc.Definition = Convert.ToString(row["QualityControlLevelDefinition"]);
  244. SeriesMetadata newSeries = new SeriesMetadata(site, v, m, qc, src);
  245. newSeries.BeginDateTime = Convert.ToDateTime(row["BeginDateTime"]);
  246. newSeries.EndDateTime = Convert.ToDateTime(row["EndDateTime"]);
  247. newSeries.BeginDateTimeUTC = Convert.ToDateTime(row["BeginDateTimeUTC"]);
  248. newSeries.EndDateTimeUTC = Convert.ToDateTime(row["EndDateTimeUTC"]);
  249. newSeries.ValueCount = Convert.ToInt32(row["ValueCount"]);
  250. DataServiceInfo servInfo = new DataServiceInfo();
  251. servInfo.EndpointURL = Convert.ToString(row["ServiceEndpointURL"]);
  252. //servInfo.ServiceCode = Convert.ToString(row["ServiceCode"]);
  253. newSeries.DataService = servInfo;
  254. return newSeries;
  255. }
  256. /// <summary>
  257. /// Converts DataRow into SeriesDataCart
  258. /// </summary>
  259. /// <param name="row">DataRow to convert</param>
  260. /// <returns>SeriesDataCart</returns>
  261. public SeriesDataCart SeriesDataCartFromRow(DataRow row)
  262. {
  263. var result = new SeriesDataCart();
  264. result.SiteName = Convert.ToString(row["SiteName"]);
  265. result.SiteCode = Convert.ToString(row["SiteCode"]);
  266. result.Latitude = Convert.ToDouble(row["Latitude"], CultureInfo.InvariantCulture);
  267. result.Longitude = Convert.ToDouble(row["Longitude"], CultureInfo.InvariantCulture);
  268. //Variable v = new Variable();
  269. result.VariableName = Convert.ToString(row["VariableName"]);
  270. result.VariableCode = Convert.ToString(row["VariableCode"]);
  271. result.DataType = Convert.ToString(row["DataType"]);
  272. result.ValueType = Convert.ToString(row["ValueType"]);
  273. result.SampleMedium = Convert.ToString(row["SampleMedium"]);
  274. result.TimeSupport = Convert.ToDouble(row["TimeSupport"], CultureInfo.InvariantCulture);
  275. result.GeneralCategory = Convert.ToString(row["GeneralCategory"]);
  276. result.TimeUnit = Convert.ToString(row["TimeUnitsName"]);
  277. result.BeginDate = Convert.ToDateTime(row["BeginDateTime"], CultureInfo.InvariantCulture);
  278. result.EndDate = Convert.ToDateTime(row["EndDateTime"], CultureInfo.InvariantCulture);
  279. result.ValueCount = Convert.ToInt32(row["ValueCount"]);
  280. result.ServURL = Convert.ToString(row["ServiceEndpointURL"]);
  281. result.ServCode = Convert.ToString(row["ServiceTitle"]);
  282. return result;
  283. }
  284. /// <summary>
  285. /// Gets a list of all data series within the bounding box
  286. /// </summary>
  287. /// <param name="xMin">minimum X (longitude)</param>
  288. /// <param name="xMax">maximum X (longitude)</param>
  289. /// <param name="yMin">minimum Y (latitude)</param>
  290. /// <param name="yMax">maximum Y (latitude)</param>
  291. /// <returns>the list of data series metadata matching the search criteria</returns>
  292. public IList<SeriesDataCart> GetSeriesListInBox ( double xMin, double xMax, double yMin, double yMax )
  293. {
  294. string sql1 = DetailedSeriesSQLQuery();
  295. string sqlWhere = " WHERE Latitude > @minlat AND Latitude <= @maxlat AND Longitude > @minlon AND Longitude <= @maxlon";
  296. string sql = sql1 + sqlWhere;
  297. DbCommand cmd = _db.CreateCommand(sql);
  298. //lat, lon parameters
  299. _db.AddParameter(cmd, "@minlat", DbType.Double);
  300. _db.AddParameter(cmd, "@maxlat", DbType.Double);
  301. _db.AddParameter(cmd, "@minlon", DbType.Double);
  302. _db.AddParameter(cmd, "@maxlon", DbType.Double);
  303. cmd.Parameters[0].Value = yMin;
  304. cmd.Parameters[1].Value = yMax;
  305. cmd.Parameters[2].Value = xMin;
  306. cmd.Parameters[3].Value = xMax;
  307. DataTable seriesTable = _db.LoadTable("seriesTable", cmd);
  308. //DataTable seriesTable = _db.LoadTable("seriesTable", sql);
  309. IList<SeriesDataCart> lst = new List<SeriesDataCart>();
  310. foreach (DataRow row in seriesTable.Rows)
  311. {
  312. SeriesDataCart newSeries = SeriesDataCartFromRow(row);
  313. lst.Add(newSeries);
  314. }
  315. return lst;
  316. }
  317. /// <summary>
  318. /// Gets a data table of all data series within the bounding box
  319. /// </summary>
  320. /// <param name="xMin">minimum X (longitude)</param>
  321. /// <param name="xMax">maximum X (longitude)</param>
  322. /// <param name="yMin">minimum Y (latitude)</param>
  323. /// <param name="yMax">maximum Y (latitude)</param>
  324. /// <param name="conceptCodes">array of Concept keywords</param>
  325. /// <param name="startDate">start date</param>
  326. /// <param name="endDate">end date</param>
  327. /// <param name="networkIDs">larray of service codes</param>
  328. /// <returns>the list of data series metadata matching the search criteria</returns>
  329. public DataTable GetSeriesDataTableInBox ( double xMin, double xMax, double yMin, double yMax, string[] conceptCodes, DateTime startDate, DateTime endDate, int[] networkIDs )
  330. {
  331. string sql1 = DetailedSeriesSQLQuery();
  332. string sqlWhere1 = " WHERE Latitude > @minlat AND Latitude < @maxlat AND Longitude > @minlon AND Longitude < @maxlon";
  333. string sqlWhere2 = "";
  334. //concept keywords | variable names
  335. if (conceptCodes == null)
  336. {
  337. sqlWhere2 = "";
  338. }
  339. else if (conceptCodes.Length == 0)
  340. {
  341. sqlWhere2 = "";
  342. }
  343. else if (string.IsNullOrEmpty(conceptCodes[0]))
  344. {
  345. sqlWhere2 = "";
  346. }
  347. else if (conceptCodes.Length == 1)
  348. {
  349. sqlWhere2 = " AND VariableName = '" + conceptCodes[0] + "'";
  350. }
  351. else if (conceptCodes.Length > 1)
  352. {
  353. sqlWhere2 = " AND VariableName IN (";
  354. foreach (string keyword in conceptCodes)
  355. {
  356. sqlWhere2 += "'" + keyword + "',";
  357. }
  358. if (sqlWhere2.EndsWith(","))
  359. {
  360. sqlWhere2 = sqlWhere2.Substring(0, sqlWhere2.Length - 1);
  361. }
  362. sqlWhere2 += ")";
  363. }
  364. //date and time
  365. string sqlWhere3 = " AND ( (BeginDateTime < @p1 AND EndDateTime > @p2) OR (BeginDateTime > @p1 AND BeginDateTime <= @p2) OR (EndDateTime > @p1 AND EndDateTime <= @p2) )";
  366. //network IDs
  367. string sqlWhere4 = "";
  368. if (networkIDs != null)
  369. {
  370. if (networkIDs.Length == 1)
  371. {
  372. sqlWhere4 = " AND DataSeriesCache.ServiceID = " + networkIDs[0];
  373. }
  374. else if (networkIDs.Length > 1)
  375. {
  376. sqlWhere4 = " AND DataSeriesCache.ServiceID IN (";
  377. foreach (int servID in networkIDs)
  378. {
  379. sqlWhere4 += servID.ToString() + ",";
  380. }
  381. if (sqlWhere4.EndsWith(","))
  382. {
  383. sqlWhere4 = sqlWhere4.Substring(0, sqlWhere4.Length - 1);
  384. }
  385. sqlWhere4 += ")";
  386. }
  387. }
  388. string sql = sql1 + sqlWhere1 + sqlWhere2 + sqlWhere3 + sqlWhere4;
  389. DbCommand cmd = _db.CreateCommand(sql);
  390. //lat, lon parameters
  391. _db.AddParameter(cmd, "@minlat", DbType.Double);
  392. _db.AddParameter(cmd, "@maxlat", DbType.Double);
  393. _db.AddParameter(cmd, "@minlon", DbType.Double);
  394. _db.AddParameter(cmd, "@maxlon", DbType.Double);
  395. _db.AddParameter(cmd, "@p1", DbType.DateTime);
  396. _db.AddParameter(cmd, "@p2", DbType.DateTime);
  397. cmd.Parameters[0].Value = yMin;
  398. cmd.Parameters[1].Value = yMax;
  399. cmd.Parameters[2].Value = xMin;
  400. cmd.Parameters[3].Value = xMax;
  401. cmd.Parameters[4].Value = startDate;
  402. cmd.Parameters[5].Value = endDate;
  403. var seriesTable = _db.LoadTable("seriesTable", cmd);
  404. return seriesTable;
  405. }
  406. /// <summary>
  407. /// Gets a list of all data series within the bounding box
  408. /// </summary>
  409. /// <param name="xMin">minimum X (longitude)</param>
  410. /// <param name="xMax">maximum X (longitude)</param>
  411. /// <param name="yMin">minimum Y (latitude)</param>
  412. /// <param name="yMax">maximum Y (latitude)</param>
  413. /// <param name="conceptCodes">array of Concept keywords</param>
  414. /// <param name="startDate">start date</param>
  415. /// <param name="endDate">end date</param>
  416. /// <param name="networkIDs">larray of service codes</param>
  417. /// <returns>the list of data series metadata matching the search criteria</returns>
  418. public IList<SeriesDataCart> GetSeriesListInBox(double xMin, double xMax, double yMin, double yMax, string[] conceptCodes, DateTime startDate, DateTime endDate, int[] networkIDs)
  419. {
  420. var dt = GetSeriesDataTableInBox(xMin, xMax, yMin, yMax, conceptCodes, startDate, endDate, networkIDs);
  421. return (from DataRow row in dt.Rows select SeriesDataCartFromRow(row)).ToList();
  422. }
  423. /// <summary>
  424. /// Gets all variables that are currently stored in the metadata cache database
  425. /// </summary>
  426. public IList<Variable> GetVariables()
  427. {
  428. string sql = "SELECT * FROM VariablesCache";
  429. DataTable tbl = _db.LoadTable(sql);
  430. List<Variable> variables = new List<Variable>();
  431. foreach (DataRow row in tbl.Rows)
  432. {
  433. Variable v = VariableFromDataRow(row);
  434. variables.Add(v);
  435. }
  436. return variables;
  437. }
  438. /// <summary>
  439. /// Gets all variables that are currently stored in the metadata cache database
  440. /// </summary>
  441. public IList<Variable> GetVariablesByService(int serviceID)
  442. {
  443. string sql = "SELECT * FROM VariablesCache WHERE serviceID=" + serviceID;
  444. DataTable tbl = _db.LoadTable(sql);
  445. List<Variable> variables = new List<Variable>();
  446. foreach (DataRow row in tbl.Rows)
  447. {
  448. Variable v = VariableFromDataRow(row);
  449. variables.Add(v);
  450. }
  451. return variables;
  452. }
  453. /// <summary>
  454. /// Gets the names of all variables accessible by the specific web service
  455. /// </summary>
  456. /// <returns></returns>
  457. public IList<string> GetVariableNamesByService(int serviceID)
  458. {
  459. string sql = "SELECT DISTINCT VariableName FROM VariablesCache WHERE ServiceID = " + serviceID;
  460. DataTable tbl = _db.LoadTable(sql);
  461. List<string> variableNames = new List<string>();
  462. foreach (DataRow row in tbl.Rows)
  463. {
  464. variableNames.Add(row["VariableName"].ToString());
  465. }
  466. return variableNames;
  467. }
  468. /// <summary>
  469. /// Gets the names of all variables that are currently stored in the metadata cache DB
  470. /// </summary>
  471. /// <returns></returns>
  472. public IList<string> GetVariableNames()
  473. {
  474. string sql = "SELECT DISTINCT VariableName FROM VariablesCache";
  475. DataTable tbl = _db.LoadTable(sql);
  476. List<string> variableNames = new List<string>();
  477. foreach (DataRow row in tbl.Rows)
  478. {
  479. variableNames.Add(row["VariableName"].ToString());
  480. }
  481. return variableNames;
  482. }
  483. /// <summary>
  484. /// Saves a new data service object to the database. If an entry with the same
  485. /// web service URL already exists in the database, update it.
  486. /// </summary>
  487. /// <param name="service">the ServiceInfo object to be saved to the DB</param>
  488. public void SaveDataService ( DataServiceInfo service )
  489. {
  490. string sqlInsert =
  491. "INSERT INTO DataServices(" +
  492. "ServiceCode, ServiceName, ServiceType, ServiceVersion, ServiceProtocol, " +
  493. "ServiceEndpointURL, ServiceDescriptionURL, NorthLatitude, SouthLatitude, EastLongitude, WestLongitude, " +
  494. "Abstract, ContactName, ContactEmail, Citation, IsHarvested, HarveDateTime, ServiceTitle) " +
  495. "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
  496. using (DbConnection conn = _db.CreateConnection())
  497. {
  498. conn.Open();
  499. using (DbTransaction tran = conn.BeginTransaction())
  500. {
  501. using (DbCommand cmd = conn.CreateCommand())
  502. {
  503. cmd.CommandText = sqlInsert;
  504. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.ServiceCode));
  505. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.ServiceName));
  506. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.ServiceType));
  507. cmd.Parameters.Add(_db.CreateParameter(DbType.Double, service.Version));
  508. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.Protocol));
  509. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.EndpointURL));
  510. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.DescriptionURL));
  511. cmd.Parameters.Add(_db.CreateParameter(DbType.Double, service.NorthLatitude));
  512. cmd.Parameters.Add(_db.CreateParameter(DbType.Double, service.SouthLatitude));
  513. cmd.Parameters.Add(_db.CreateParameter(DbType.Double, service.EastLongitude));
  514. cmd.Parameters.Add(_db.CreateParameter(DbType.Double, service.WestLongitude));
  515. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.Abstract));
  516. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.ContactName));
  517. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.ContactEmail));
  518. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.Citation));
  519. cmd.Parameters.Add(_db.CreateParameter(DbType.Boolean, service.IsHarvested));
  520. cmd.Parameters.Add(_db.CreateParameter(DbType.DateTime, service.HarveDateTime));
  521. cmd.Parameters.Add(_db.CreateParameter(DbType.String, service.ServiceTitle));
  522. cmd.ExecuteNonQuery();
  523. }
  524. tran.Commit();
  525. }
  526. }
  527. }
  528. /// <summary>
  529. /// Deletes all entries in the metadata cache database that were
  530. /// added by the data service
  531. /// </summary>
  532. /// <param name="service">The serviceInfo object to be deleted</param>
  533. /// <param name="deleteService">Set to true if the record in the DataServices
  534. /// table should also be deleted. Set to false if the record in the DataServices
  535. /// table should be kept</param>
  536. /// <returns>The total number of records deleted</returns>
  537. public int DeleteRecordsForService ( DataServiceInfo service, bool deleteService )
  538. {
  539. string serviceID = service.Id.ToString();
  540. string sqlDelete = "DELETE FROM DataSeriesCache WHERE ServiceID = " + serviceID + "; " +
  541. "DELETE FROM SitesCache WHERE ServiceID = " + serviceID + "; " +
  542. "DELETE FROM VariablesCache WHERE ServiceID = " + serviceID + "; " +
  543. "DELETE FROM SourcesCache WHERE ServiceID = " + serviceID + "; " +
  544. "DELETE FROM MethodsCache WHERE ServiceID = " + serviceID + "; " +
  545. "DELETE FROM QualityControlLevelsCache WHERE ServiceID = " + serviceID + ";" +
  546. "DELETE FROM ISOMetadataCache WHERE ServiceID = " + serviceID + ";";
  547. if ( deleteService == true )
  548. {
  549. sqlDelete += "DELETE FROM DataServices WHERE ServiceID = " + serviceID + ";";
  550. }
  551. using (DbConnection conn = _db.CreateConnection())
  552. {
  553. conn.Open();
  554. using (DbTransaction tran = conn.BeginTransaction())
  555. {
  556. using (DbCommand cmd01 = conn.CreateCommand())
  557. {
  558. cmd01.CommandText = sqlDelete;
  559. cmd01.ExecuteNonQuery();
  560. }
  561. tran.Commit();
  562. }
  563. }
  564. return 0;
  565. }
  566. /// <summary>
  567. /// Deletes a series given it's ID. The series is only deleted when it belongs to one theme.
  568. /// </summary>
  569. /// <param name="seriesID">The database ID of the series</param>
  570. /// <returns>true if series was deleted, false otherwise</returns>
  571. public bool DeleteSeries(int seriesID)
  572. {
  573. int siteID = 0;
  574. int variableID = 0;
  575. int sourceID = 0;
  576. int qualityID = 0;
  577. int methodID = 0;
  578. string sqlSeries = "SELECT SiteID, VariableID, MethodID, SourceID, QualityControlLevelID " +
  579. "FROM DataSeriesCache WHERE SeriesID = " + seriesID;
  580. DataTable seriesTable = _db.LoadTable("seriesTable", sqlSeries);
  581. if (seriesTable.Rows.Count == 0) return false;
  582. DataRow seriesRow = seriesTable.Rows[0];
  583. siteID = Convert.ToInt32(seriesRow["SiteID"]);
  584. variableID = Convert.ToInt32(seriesRow["VariableID"]);
  585. methodID = Convert.ToInt32(seriesRow["MethodID"]);
  586. sourceID = Convert.ToInt32(seriesRow["SourceID"]);
  587. qualityID = Convert.ToInt32(seriesRow["QualityControlLevelID"]);
  588. //SQL Queries
  589. string sqlSite = "SELECT SiteID from DataSeriesCache where SiteID = " + siteID;
  590. string sqlVariable = "SELECT VariableID from DataSeriesCache where VariableID = " + variableID;
  591. string sqlSource = "SELECT SourceID from DataSeriesCache where SourceID = " + sourceID;
  592. string sqlMethod = "SELECT MethodID from DataSeriesCache where MethodID = " + methodID;
  593. string sqlQuality = "SELECT QualityControlLevelID from DataSeriesCache where QualityControlLevelID = " + qualityID;
  594. //SQL Delete Commands
  595. string sqlDeleteSeries = "DELETE FROM DataSeriesCache WHERE SeriesID = " + seriesID;
  596. string sqlDeleteSite = "DELETE FROM SitesCache WHERE SiteID = " + siteID;
  597. string sqlDeleteVariable = "DELETE FROM VariablesCache WHERE VariableID = " + variableID;
  598. string sqlDeleteMethod = "DELETE FROM MethodsCache WHERE MethodID = " + methodID;
  599. string sqlDeleteSource = "DELETE FROM SourcesCache WHERE SourceID = " + sourceID;
  600. string sqlDeleteQuality = "DELETE FROM QualityControlLevelsCache WHERE QualityControlLevelID = " + qualityID;
  601. DataTable tblSite = new DataTable();
  602. DataTable tblVariable = new DataTable();
  603. DataTable tblSource = new DataTable();
  604. DataTable tblMethod = new DataTable();
  605. DataTable tblQuality = new DataTable();
  606. //Begin Transaction
  607. using (DbConnection conn = _db.CreateConnection())
  608. {
  609. conn.Open();
  610. using (DbTransaction tran = conn.BeginTransaction())
  611. {
  612. // get site IDs
  613. using (DbCommand cmd01 = conn.CreateCommand())
  614. {
  615. cmd01.CommandText = sqlSite;
  616. tblSite = _db.LoadTable("t1", cmd01);
  617. }
  618. // get variable IDs
  619. using (DbCommand cmd02 = conn.CreateCommand())
  620. {
  621. cmd02.CommandText = sqlVariable;
  622. tblVariable = _db.LoadTable("t2", cmd02);
  623. }
  624. // get source IDs
  625. using (DbCommand cmd03 = conn.CreateCommand())
  626. {
  627. cmd03.CommandText = sqlSource;
  628. tblSource = _db.LoadTable("t3", cmd03);
  629. }
  630. // get method IDs
  631. using (DbCommand cmd04 = conn.CreateCommand())
  632. {
  633. cmd04.CommandText = sqlMethod;
  634. tblMethod = _db.LoadTable("t4", cmd04);
  635. }
  636. // get qualityControl IDs
  637. using (DbCommand cmd05 = conn.CreateCommand())
  638. {
  639. cmd05.CommandText = sqlQuality;
  640. tblQuality = _db.LoadTable("t5", cmd05);
  641. }
  642. //delete the site
  643. if (tblSite.Rows.Count == 1)
  644. {
  645. using (DbCommand cmdDeleteSite = conn.CreateCommand())
  646. {
  647. cmdDeleteSite.CommandText = sqlDeleteSite;
  648. cmdDeleteSite.ExecuteNonQuery();
  649. }
  650. }
  651. //delete the variable
  652. if (tblVariable.Rows.Count == 1)
  653. {
  654. using (DbCommand cmdDeleteVariable = conn.CreateCommand())
  655. {
  656. cmdDeleteVariable.CommandText = sqlDeleteVariable;
  657. cmdDeleteVariable.ExecuteNonQuery();
  658. }
  659. }
  660. //delete the method
  661. if (tblMethod.Rows.Count == 1)
  662. {
  663. using (DbCommand cmdDeleteMethod = conn.CreateCommand())
  664. {
  665. cmdDeleteMethod.CommandText = sqlDeleteMethod;
  666. cmdDeleteMethod.ExecuteNonQuery();
  667. }
  668. }
  669. //delete the source
  670. if (tblSource.Rows.Count == 1)
  671. {
  672. using (DbCommand cmdDeleteSource = conn.CreateCommand())
  673. {
  674. cmdDeleteSource.CommandText = sqlDeleteSource;
  675. cmdDeleteSource.ExecuteNonQuery();
  676. }
  677. }
  678. //delete the quality control level
  679. if (tblQuality.Rows.Count == 1)
  680. {
  681. using (DbCommand cmdDeleteQuality = conn.CreateCommand())
  682. {
  683. cmdDeleteQuality.CommandText = sqlDeleteQuality;
  684. cmdDeleteQuality.ExecuteNonQuery();
  685. }
  686. }
  687. //finally delete the series
  688. using (DbCommand cmdDeleteSeries = conn.CreateCommand())
  689. {
  690. cmdDeleteSeries.CommandText = sqlDeleteSeries;
  691. cmdDeleteSeries.ExecuteNonQuery();
  692. }
  693. //commit transaction
  694. tran.Commit();
  695. }
  696. }
  697. return true;
  698. }
  699. /// <summary>
  700. /// Check if the series with the same site, variable, method,
  701. /// source, quality control level and data service already
  702. /// exists in the database.
  703. /// </summary>
  704. /// <param name="seriesToCheck">the series to be checked</param>
  705. /// <returns>The series from the db, or NULL if it doesn't exist</returns>
  706. /// <remarks>Not implemented</remarks>
  707. private SeriesMetadata CheckIfSeriesExists ( SeriesMetadata seriesToCheck )
  708. {
  709. throw new NotImplementedException();
  710. }
  711. /// <summary>
  712. /// Saves the series metadata to the metadata cache database.
  713. /// This method also automatically saves the site, variable,
  714. /// method, source and quality control level of the series.
  715. /// </summary>
  716. /// <param name="series">The series to be saved</param>
  717. /// <param name="dataService">The web service containing the series</param>
  718. public void SaveSeries ( SeriesMetadata series, DataServiceInfo dataService )
  719. {
  720. string sqlSite = "SELECT SiteID FROM SitesCache WHERE SiteCode = ?";
  721. string sqlVariable = "SELECT VariableID FROM VariablesCache WHERE VariableCode = ?";
  722. string sqlMethod = "SELECT MethodID FROM MethodsCache WHERE MethodDescription = ?";
  723. string sqlSource = "SELECT SourceID FROM SourcesCache WHERE Organization = ?";
  724. string sqlQuality = "SELECT QualityControlLevelID FROM QualityControlLevelsCache WHERE Definition = ?";
  725. string sqlRowID = "; SELECT LAST_INSERT_ROWID();";
  726. string sqlSaveSite = "INSERT INTO SitesCache(SiteCode, SiteName, Latitude, Longitude, LatLongDatumSRSID, LatLongDatumName, " +
  727. "Elevation_m, VerticalDatum, LocalX, LocalY, LocalProjectionSRSID, LocalProjectionName, " +
  728. "PosAccuracy_m, State, County, Comments, ServiceID) " +
  729. "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + sqlRowID;
  730. string sqlSaveVariable = "INSERT INTO variablesCache(VariableCode, VariableName, Speciation, " +
  731. "SampleMedium, ValueType, DataType, GeneralCategory, NoDataValue, VariableUnitsName, VariableUnitsType, VariableUnitsAbbreviation, " +
  732. "IsRegular, TimeSupport, TimeUnitsName, TimeUnitsType, TimeUnitsAbbreviation, ServiceID) " +
  733. "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + sqlRowID;
  734. string sqlSaveMethod = "INSERT INTO MethodsCache(OriginMethodID, MethodDescription, MethodLink, ServiceID) VALUES(?, ?, ?, ?)" + sqlRowID;
  735. string sqlSaveQualityControl = "INSERT INTO QualityControlLevelsCache(OriginQualityControlLevelID, QualityControlLevelCode, Definition, Explanation) " +
  736. "VALUES(?,?,?,?)" + sqlRowID;
  737. string sqlSaveSource = "INSERT INTO SourcesCache(OriginSourceID, Organization, SourceDescription, SourceLink, ContactName, Phone, " +
  738. "Email, Address, City, State, ZipCode, Citation, MetadataID) " +
  739. "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + sqlRowID;
  740. string sqlSaveISOMetadata = "INSERT INTO ISOMetadataCache(TopicCategory, Title, Abstract, ProfileVersion, MetadataLink) " +
  741. "VALUES(?, ?, ?, ?, ?)" + sqlRowID;
  742. string sqlSaveSeries = "INSERT INTO DataSeriesCache(SiteID, VariableID, MethodID, SourceID, QualityControlLevelID, " +
  743. "BeginDateTime, EndDateTime, BeginDateTimeUTC, EndDateTimeUTC, ValueCount, ServiceID) " +
  744. "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + sqlRowID;
  745. int siteID = 0;
  746. int variableID = 0;
  747. int methodID = 0;
  748. int qualityControlLevelID = 0;
  749. int sourceID = 0;
  750. int isoMetadataID = 0;
  751. int seriesID = 0;
  752. object siteIDResult = null;
  753. object variableIDResult = null;
  754. object methodIDResult = null;
  755. object qualityControlLevelIDResult = null;
  756. object sourceIDResult = null;
  757. object seriesIDResult = null;
  758. //check the ServiceID (must be already set)
  759. if (dataService.Id <= 0)
  760. {
  761. throw new ArgumentException("The DataServiceID must be set.");
  762. }
  763. //Step 1 Begin Transaction
  764. using (DbConnection conn = _db.CreateConnection())
  765. {
  766. conn.Open();
  767. using (DbTransaction tran = conn.BeginTransaction())
  768. {
  769. //****************************************************************
  770. //*** Step 2 Site
  771. //****************************************************************
  772. using (DbCommand cmd01 = conn.CreateCommand())
  773. {
  774. cmd01.CommandText = sqlSite;
  775. cmd01.Parameters.Add(_db.CreateParameter(DbType.String, series.Site.Code));
  776. siteIDResult = cmd01.ExecuteScalar();
  777. if (siteIDResult != null)
  778. {
  779. siteID = Convert.ToInt32(siteIDResult);
  780. }
  781. }
  782. if (siteID == 0) //New Site needs to be created
  783. {
  784. //Insert the site to the database
  785. using (DbCommand cmd04 = conn.CreateCommand())
  786. {
  787. Site site = series.Site;
  788. cmd04.CommandText = sqlSaveSite;
  789. cmd04.Parameters.Add(_db.CreateParameter(DbType.String, site.Code));
  790. cmd04.Parameters.Add(_db.CreateParameter(DbType.String, site.Name));
  791. cmd04.Parameters.Add(_db.CreateParameter(DbType.Double, site.Latitude));
  792. cmd04.Parameters.Add(_db.CreateParameter(DbType.Double, site.Longitude));
  793. cmd04.Parameters.Add(_db.CreateParameter(DbType.Int32, site.SpatialReference.SRSID));
  794. cmd04.Parameters.Add(_db.CreateParameter(DbType.String, site.SpatialReference.SRSName));
  795. cmd04.Parameters.Add(_db.CreateParameter(DbType.Double, site.Elevation_m));
  796. cmd04.Parameters.Add(_db.CreateParameter(DbType.String, site.VerticalDatum));
  797. cmd04.Parameters.Add(_db.CreateParameter(DbType.Double, site.LocalX));
  798. cmd04.Parameters.Add(_db.CreateParameter(DbType.Double, site.LocalY));
  799. if (site.LocalProjection != null)
  800. {
  801. cmd04.Parameters.Add(_db.CreateParameter(DbType.Int32, site.LocalProjection.SRSID));
  802. cmd04.Parameters.Add(_db.CreateParameter(DbType.String, site.LocalProjection.SRSName));
  803. }
  804. else
  805. {
  806. cmd04.Parameters.Add(_db.CreateParameter(DbType.Int32, 0));
  807. cmd04.Parameters.Add(_db.CreateParameter(DbType.String, "unknown"));
  808. }
  809. cmd04.Parameters.Add(_db.CreateParameter(DbType.Double, site.PosAccuracy_m));
  810. cmd04.Parameters.Add(_db.CreateParameter(DbType.String, site.State));
  811. cmd04.Parameters.Add(_db.CreateParameter(DbType.String, site.County));
  812. cmd04.Parameters.Add(_db.CreateParameter(DbType.String, site.Comments));
  813. cmd04.Parameters.Add(_db.CreateParameter(DbType.Int32, dataService.Id));
  814. siteIDResult = cmd04.ExecuteScalar();
  815. siteID = Convert.ToInt32(siteIDResult);
  816. }
  817. }
  818. //****************************************************************
  819. //*** Step 3 Variable
  820. //****************************************************************
  821. Variable variable = series.Variable;
  822. using (DbCommand cmd05 = conn.CreateCommand())
  823. {
  824. cmd05.CommandText = sqlVariable;
  825. cmd05.Parameters.Add(_db.CreateParameter(DbType.String, variable.Code));
  826. cmd05.Parameters[0].Value = variable.Code;
  827. variableIDResult = cmd05.ExecuteScalar();
  828. if (variableIDResult != null)
  829. {
  830. variableID = Convert.ToInt32(variableIDResult);
  831. }
  832. }
  833. if (variableID == 0) //New variable needs to be created
  834. {
  835. //Insert the variable to the database
  836. using (DbCommand cmd09 = conn.CreateCommand())
  837. {
  838. cmd09.CommandText = sqlSaveVariable;
  839. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.Code));
  840. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.Name));
  841. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.Speciation));
  842. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.SampleMedium));
  843. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.ValueType));
  844. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.DataType));
  845. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.GeneralCategory));
  846. cmd09.Parameters.Add(_db.CreateParameter(DbType.Double, variable.NoDataValue));
  847. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.VariableUnit.Name));
  848. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.VariableUnit.UnitsType));
  849. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.VariableUnit.Abbreviation));
  850. cmd09.Parameters.Add(_db.CreateParameter(DbType.Boolean, variable.IsRegular));
  851. cmd09.Parameters.Add(_db.CreateParameter(DbType.Double, variable.TimeSupport));
  852. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.TimeUnit.Name));
  853. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.TimeUnit.UnitsType));
  854. cmd09.Parameters.Add(_db.CreateParameter(DbType.String, variable.TimeUnit.Abbreviation));
  855. cmd09.Parameters.Add(_db.CreateParameter(DbType.Int32, dataService.Id));
  856. variableIDResult = cmd09.ExecuteScalar();
  857. variableID = Convert.ToInt32(variableIDResult);
  858. }
  859. }
  860. //****************************************************************
  861. //*** Step 4 Method
  862. //****************************************************************
  863. Method method = series.Method;
  864. using (DbCommand cmd10 = conn.CreateCommand())
  865. {
  866. cmd10.CommandText = sqlMethod;
  867. cmd10.Parameters.Add(_db.CreateParameter(DbType.String, method.Description));
  868. methodIDResult = cmd10.ExecuteScalar();
  869. if (methodIDResult != null)
  870. {
  871. methodID = Convert.ToInt32(methodIDResult);
  872. }
  873. }
  874. if (methodID == 0)
  875. {
  876. using (DbCommand cmd11 = conn.CreateCommand())
  877. {
  878. cmd11.CommandText = sqlSaveMethod;
  879. cmd11.Parameters.Add(_db.CreateParameter(DbType.Int32, method.Code));
  880. cmd11.Parameters.Add(_db.CreateParameter(DbType.String, method.Description));
  881. cmd11.Parameters.Add(_db.CreateParameter(DbType.String, method.Link));
  882. cmd11.Parameters.Add(_db.CreateParameter(DbType.Int32, dataService.Id));
  883. methodIDResult = cmd11.ExecuteScalar();
  884. methodID = Convert.ToInt32(methodIDResult);
  885. }
  886. }
  887. //****************************************************************
  888. //*** Step 5 Quality Control Level
  889. //****************************************************************
  890. QualityControlLevel qc = series.QualityControlLevel;
  891. using (DbCommand cmd12 =