PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/services/Controllers/DataActionController.cs

https://github.com/CTUIR/cdms-services
C# | 1744 lines | 1173 code | 389 blank | 182 comment | 173 complexity | 8b8f3b21207a715e78aa91cc0c7e57c5 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Configuration;
  5. using System.Data;
  6. using System.Transactions;
  7. using System.Data.Common;
  8. using System.Data.SqlClient;
  9. using System.IO;
  10. using System.Linq;
  11. using System.Linq.Dynamic;
  12. using System.Net;
  13. using System.Net.Http;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. using System.Web;
  17. using System.Web.Http;
  18. using CsvHelper;
  19. using Newtonsoft.Json;
  20. using Newtonsoft.Json.Linq;
  21. using NLog;
  22. using services.Models;
  23. using services.Models.Data;
  24. using services.Resources;
  25. namespace services.Controllers
  26. {
  27. [Authorize]
  28. public partial class DataActionController : ApiController
  29. {
  30. private static Logger logger = LogManager.GetCurrentClassLogger();
  31. public DataTable GetHeadersDataForDataset(int id)
  32. {
  33. var db = ServicesContext.Current;
  34. Dataset dataset = db.Datasets.Find(id);
  35. if (dataset == null)
  36. {
  37. throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
  38. }
  39. string query = "SELECT h.* FROM " + dataset.Datastore.TablePrefix + "_Header_VW h JOIN Activities a on a.Id = h.ActivityId WHERE a.DatasetId = " + dataset.Id;
  40. DataTable dt = new DataTable();
  41. using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServicesContext"].ConnectionString))
  42. {
  43. using (SqlCommand cmd = new SqlCommand(query, con))
  44. {
  45. con.Open();
  46. SqlDataAdapter da = new SqlDataAdapter(cmd);
  47. da.Fill(dt);
  48. }
  49. }
  50. return dt;
  51. }
  52. [HttpPost]
  53. public IEnumerable<MetadataValue> GetMetadataFor(JObject jsonData)
  54. {
  55. var db = ServicesContext.Current;
  56. dynamic json = jsonData;
  57. User me = AuthorizationManager.getCurrentUser();
  58. Project project = db.Projects.Find(json.ProjectId.ToObject<int>());
  59. int EntityTypeId = json.EntityTypeId.ToObject<int>();
  60. if (project == null || me == null)
  61. throw new Exception("Configuration error. Please try again.");
  62. return MetadataHelper.getMetadata(project.Id, EntityTypeId).AsEnumerable();
  63. }
  64. [HttpGet]
  65. public IEnumerable<Dataset> GetMyDatasets()
  66. {
  67. var db = ServicesContext.Current;
  68. User me = AuthorizationManager.getCurrentUser();
  69. var mydatasets = "";
  70. try
  71. {
  72. mydatasets = me.UserPreferences.Where(o => o.Name == UserPreference.DATASETS).FirstOrDefault().Value;
  73. }
  74. catch (Exception e)
  75. {
  76. logger.Debug("Couldn't get your datasets -- probably don't have any favorites.");
  77. logger.Debug(e);
  78. }
  79. var datasets = db.Datasets.SqlQuery("SELECT * FROM Datasets WHERE Id in (" + mydatasets +") ORDER BY Name");
  80. return datasets;
  81. }
  82. [HttpGet]
  83. public IEnumerable<Project> GetMyProjects()
  84. {
  85. var db = ServicesContext.Current;
  86. User me = AuthorizationManager.getCurrentUser();
  87. var my_projects = "";
  88. try
  89. {
  90. my_projects = me.UserPreferences.Where(o => o.Name == UserPreference.PROJECTS).FirstOrDefault().Value;
  91. }
  92. catch (Exception e)
  93. {
  94. logger.Debug("Couldn't get your projects -- probably don't have any favorites.");
  95. logger.Debug(e);
  96. }
  97. var myprojects = db.Projects.SqlQuery("SELECT * FROM Projects WHERE Id in (" + my_projects + ") ORDER BY Name");
  98. return myprojects;
  99. }
  100. [HttpPost]
  101. public HttpResponseMessage SetQaStatus(JObject jsonData)
  102. {
  103. var db = ServicesContext.Current;
  104. dynamic json = jsonData;
  105. User me = AuthorizationManager.getCurrentUser();
  106. Activity activity = db.Activities.Find(json.ActivityId.ToObject<int>());
  107. if (activity == null || me == null)
  108. throw new Exception("Configuration error. Please try again.");
  109. logger.Debug("Userid = " + me.Id + " Activity = " + activity.Id);
  110. //TODO: verify that the user is authorized to modify this activity? -- yes, that would be nice. (or add Authorized annotation) TODO!
  111. var aq = new ActivityQA();
  112. aq.ActivityId = activity.Id;
  113. aq.EffDt = DateTime.Now;
  114. aq.Comments = json.Comments;
  115. aq.UserId = me.Id; //current user.
  116. aq.QAStatusId = json.QAStatusId;
  117. db.ActivityQAs.Add(aq);
  118. db.SaveChanges();
  119. return new HttpResponseMessage(HttpStatusCode.OK);
  120. }
  121. [HttpPost]
  122. public HttpResponseMessage SetProjectEditors(JObject jsonData)
  123. {
  124. var db = ServicesContext.Current;
  125. dynamic json = jsonData;
  126. Project project = db.Projects.Find(json.ProjectId.ToObject<int>());
  127. if (project == null)
  128. throw new Exception("Configuration error.");
  129. User me = AuthorizationManager.getCurrentUser();
  130. if (me == null)
  131. throw new Exception("Configuration error.");
  132. //verify that the sender is the project owner.
  133. if (!project.isOwnerOrEditor(me))
  134. throw new Exception("Authorization error.");
  135. //First -- remove all editors from this project.
  136. project.Editors.RemoveAll(o => o.Id > 0);
  137. db.SaveChanges();
  138. foreach (var item in json.Editors)
  139. {
  140. User user = db.User.Find(item.Id.ToObject<int>());
  141. if (user == null)
  142. logger.Debug("Wow -- user not found!: " + item.Id);
  143. else
  144. {
  145. logger.Debug("Adding: " + item.Id);
  146. project.Editors.Add(user);
  147. }
  148. }
  149. db.SaveChanges();
  150. return new HttpResponseMessage(HttpStatusCode.OK);
  151. }
  152. [HttpPost]
  153. public HttpResponseMessage SetDatasetMetadata(JObject jsonData)
  154. {
  155. var db = ServicesContext.Current;
  156. dynamic json = jsonData;
  157. Dataset dataset = db.Datasets.Find(json.DatasetId.ToObject<int>());
  158. if (dataset == null)
  159. throw new Exception("Configuration error.");
  160. Project project = db.Projects.Find(dataset.ProjectId);
  161. User me = AuthorizationManager.getCurrentUser();
  162. if (!project.isOwnerOrEditor(me))
  163. throw new Exception("Configuration error.");
  164. //Now save metadata
  165. List<MetadataValue> metadata = new List<MetadataValue>();
  166. foreach (var jmv in json.Metadata)
  167. {
  168. var mv = jmv.ToObject<MetadataValue>();
  169. mv.UserId = me.Id;
  170. metadata.Add(mv);
  171. logger.Debug("Found new metadata: " + mv.MetadataPropertyId + " + + " + mv.Values);
  172. }
  173. //fire setMetdata which will handle persisting the metadata
  174. dataset.Metadata = metadata;
  175. db.SaveChanges();
  176. return new HttpResponseMessage(HttpStatusCode.OK);
  177. }
  178. [HttpPost]
  179. public HttpResponseMessage DeleteDatasetActivities(JObject jsonData)
  180. {
  181. var db = ServicesContext.Current;
  182. dynamic json = jsonData;
  183. Dataset dataset = db.Datasets.Find(json.DatasetId.ToObject<int>());
  184. Project project = db.Projects.Find(dataset.ProjectId);
  185. if (project == null)
  186. throw new Exception("Configuration error. Please try again.");
  187. User me = AuthorizationManager.getCurrentUser();
  188. if (!project.isOwnerOrEditor(me))
  189. throw new Exception("Configuration error.");
  190. var Activities = new List<string>();
  191. foreach (var item in json.Activities)
  192. {
  193. Activities.Add(""+item.Id);
  194. }
  195. var ActivityIds = string.Join(",", Activities);
  196. var DataTable = dataset.Datastore.TablePrefix;
  197. //open a raw database connection...
  198. using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServicesContext"].ConnectionString))
  199. {
  200. con.Open();
  201. var query = "DELETE FROM " + DataTable + "_Detail WHERE ActivityId in ("+ ActivityIds + ")";
  202. using (SqlCommand cmd = new SqlCommand(query, con))
  203. {
  204. logger.Debug(query);
  205. cmd.ExecuteNonQuery();
  206. }
  207. query = "DELETE FROM " + DataTable + "_Header WHERE ActivityId in (" + ActivityIds + ")";
  208. using (SqlCommand cmd = new SqlCommand(query, con))
  209. {
  210. logger.Debug(query);
  211. cmd.ExecuteNonQuery();
  212. }
  213. query = "DELETE FROM ActivityQAs WHERE ActivityId in (" + ActivityIds + ")";
  214. using (SqlCommand cmd = new SqlCommand(query, con))
  215. {
  216. logger.Debug(query);
  217. cmd.ExecuteNonQuery();
  218. }
  219. query = "DELETE FROM Activities WHERE DatasetId = " + dataset.Id + " AND Id in (" + ActivityIds + ")";
  220. using (SqlCommand cmd = new SqlCommand(query, con))
  221. {
  222. logger.Debug(query);
  223. cmd.ExecuteNonQuery();
  224. }
  225. }
  226. return new HttpResponseMessage(HttpStatusCode.OK);
  227. }
  228. //QUERY
  229. //QueryDatasetActivities -- can call with a datasetId or a datastoreId
  230. [HttpPost]
  231. public DataTable QueryDatasetActivities(JObject jsonData)
  232. {
  233. var db = ServicesContext.Current;
  234. DataTable datatable = null;
  235. dynamic json = jsonData;
  236. //let's see if we're dealing with a dataset
  237. if (json["DatasetId"] is JToken)
  238. {
  239. //grab a reference to this dataset so we can parse incoming fields
  240. Dataset dataset = db.Datasets.Find(json.DatasetId.ToObject<int>());
  241. if (dataset == null)
  242. throw new Exception("Configuration error. Please try again.");
  243. logger.Debug("Alright! we are working with dataset: " + dataset.Id);
  244. datatable = getQueryResults(dataset, json);
  245. }
  246. //let's see if we're dealing with a datastore.
  247. if (json["DatastoreId"] is JToken)
  248. {
  249. //grab a reference to this dataset so we can parse incoming fields
  250. Datastore datastore = db.Datastores.Find(json.DatastoreId.ToObject<int>());
  251. if (datastore == null)
  252. throw new Exception("Configuration error. Please try again.");
  253. logger.Debug("Alright! we are working with datastore: " + datastore.Id);
  254. datatable = getQueryResults(datastore, json);
  255. }
  256. return datatable;
  257. }
  258. //Writes csv export file out to a file and returns the url.
  259. [HttpPost]
  260. public ExportResult DownloadDatasetActivities(JObject jsonData)
  261. {
  262. var db = ServicesContext.Current;
  263. dynamic json = jsonData;
  264. User me = AuthorizationManager.getCurrentUser();
  265. //grab a reference to this dataset so we can parse incoming fields
  266. Dataset dataset = db.Datasets.Find(json.DatasetId.ToObject<int>());
  267. if (dataset == null || me == null)
  268. throw new Exception("Configuration error. Please try again.");
  269. logger.Debug("Alright! we are working with dataset: " + dataset.Id);
  270. DataTable dt = getQueryResults(dataset, json);
  271. logger.Debug("Download data -- we have a result back.");
  272. string Filename = json.Filename;
  273. Filename = Filename.Replace("\"", string.Empty);
  274. Filename = Filename.Replace("\\", string.Empty);
  275. Filename = Filename.Replace("/", string.Empty);
  276. logger.Debug("Incomfing filename specified: " + Filename);
  277. string root = System.Web.HttpContext.Current.Server.MapPath("~/exports");
  278. string the_file = root + @"\" + dataset.Id + @"_" + me.Id + @"\" + Filename;
  279. logger.Debug("saving file to location: " + the_file);
  280. System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(the_file)); //will create if necessary.
  281. string rootUrl = Request.RequestUri.AbsoluteUri.Replace(Request.RequestUri.AbsolutePath, String.Empty);
  282. rootUrl += "/services/exports/" + dataset.Id + "_" + me.Id + "/" + Filename;
  283. using (TextWriter writer = System.IO.File.CreateText(the_file)) //will overwrite = good
  284. {
  285. using (var csv = new CsvWriter(writer))
  286. {
  287. IEnumerable<string> columnNames = dataset.getExportLabelsList();//dt.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
  288. //columns
  289. foreach (var header in columnNames)
  290. {
  291. csv.WriteField(header);
  292. }
  293. csv.NextRecord();
  294. //fields
  295. foreach (DataRow row in dt.Rows)
  296. {
  297. IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString());
  298. foreach (var field in fields)
  299. {
  300. //replace out the multiselect array stuff.
  301. var f = field.Replace("[]", string.Empty).Replace("[\"", string.Empty).Replace("\"]", string.Empty).Replace("\",\"", ",");
  302. csv.WriteField(f);
  303. }
  304. csv.NextRecord();
  305. }
  306. }
  307. }
  308. //TODO-- error handling?
  309. ExportResult result = new ExportResult();
  310. result.success = true;
  311. result.file = rootUrl;
  312. result.errors = null;
  313. return result;
  314. }
  315. [HttpPost]
  316. public HttpResponseMessage UpdateDatasetActivities(JObject jsonData)
  317. {
  318. var db = ServicesContext.Current;
  319. dynamic json = jsonData;
  320. User me = AuthorizationManager.getCurrentUser();
  321. Dataset dataset = db.Datasets.Find(json.DatasetId.ToObject<int>());
  322. if (dataset == null)
  323. throw new Exception("Configuration Error.");
  324. Project project = db.Projects.Find(dataset.ProjectId);
  325. if (project == null)
  326. throw new Exception("Configuration Error");
  327. if (!project.isOwnerOrEditor(me))
  328. throw new Exception("Authorization error.");
  329. //setup our generic data stuff
  330. var data_header_name = dataset.Datastore.TablePrefix + "_Header";
  331. var data_detail_name = dataset.Datastore.TablePrefix + "_Detail";
  332. var dbset_header = db.GetDbSet(data_header_name);
  333. var dbset_detail = db.GetDbSet(data_detail_name);
  334. var dbset_header_type = db.GetTypeFor(data_header_name);
  335. var dbset_detail_type = db.GetTypeFor(data_detail_name);
  336. foreach (var item in json.activities)
  337. {
  338. if (item is JProperty)
  339. {
  340. var prop = item as JProperty;
  341. dynamic activity_json = prop.Value;
  342. logger.Debug("Updating activity id: " + json.ActivityId);
  343. Activity activity = db.Activities.Find(json.ActivityId.ToObject<int>());
  344. if (activity == null)
  345. {
  346. throw new Exception("Invalid Activity.");
  347. }
  348. activity.LocationId = activity_json.LocationId;
  349. try
  350. {
  351. activity.ActivityDate = activity_json.ActivityDate;
  352. }
  353. catch (Exception e)
  354. {
  355. logger.Debug("Ooops had an error converting date: " + activity_json.ActivityDate);
  356. logger.Debug(e.ToString());
  357. throw (e);
  358. }
  359. //activity.DatasetId = json.DatasetId;
  360. activity.UserId = me.Id;
  361. activity.SourceId = 1; // TODO get from data
  362. activity.ActivityTypeId = 1;
  363. activity.InstrumentId = activity_json.InstrumentId;
  364. activity.AccuracyCheckId = activity_json.AccuracyCheckId;
  365. activity.PostAccuracyCheckId = activity_json.PostAccuracyCheckId;
  366. activity.Timezone = activity_json.Timezone;
  367. //activity.CreateDate = DateTime.Now;
  368. db.Entry(activity).State = EntityState.Modified;
  369. db.SaveChanges();
  370. //updated the activity
  371. logger.Debug("Updated an activity: ");
  372. logger.Debug(" LocationID = " + activity_json.LocationId);
  373. logger.Debug(" ActivityDate = " + activity_json.ActivityDate);
  374. logger.Debug(" ID = " + activity.Id);
  375. //now check our activity status -- update it if we've changed.
  376. //if(activity.ActivityQAStatus.ActivityId != )
  377. dynamic activityqastatus = activity_json.ActivityQAStatus;
  378. //logger.Debug(activity_json.ActivityQAStatus);
  379. //logger.Debug(activityqastatus.QAStatusId.ToObject<int>());
  380. ActivityQA newQA = new ActivityQA();
  381. newQA.ActivityId = activity.Id;
  382. newQA.QAStatusId = activityqastatus.QAStatusID.ToObject<int>();
  383. newQA.Comments = activityqastatus.Comments;
  384. newQA.EffDt = DateTime.Now;
  385. newQA.UserId = activity.UserId;
  386. db.ActivityQAs.Add(newQA);
  387. db.SaveChanges();
  388. //get our last header and then check against incoming header field values to see if anything has changed.
  389. var last_header_list = dbset_header.SqlQuery("SELECT * FROM " + data_header_name + " WHERE ActivityId = " + activity.Id + " ORDER BY EffDt DESC");
  390. //.SqlQuery("SELECT * FROM " + data_header_name + " WHERE ActivityId = " + activity.Id + " ORDER BY EffDt DESC").AsQueryable().f;
  391. //db.AdultWeir_Header.Where(o => o.ActivityId == activity.Id).OrderByDescending(d => d.EffDt).FirstOrDefault();
  392. var last_header = this.getFirstItem(last_header_list);
  393. logger.Debug("Ok -- here we are with our lastheader:");
  394. logger.Debug(last_header);
  395. if (last_header == null)
  396. throw new Exception("Somehow there is no previous header even though we are trying to update.");
  397. bool header_updated = false;
  398. //spin through and check the header fields for changes...
  399. foreach (JProperty header_field in activity_json.Header)
  400. {
  401. logger.Debug("Checking last header value of field : '" + header_field.Name + "' with incoming value + '" + header_field.Value+"'");
  402. var objval = last_header.GetType().GetProperty(header_field.Name).GetValue(last_header, null);
  403. if (objval != null)
  404. {
  405. logger.Debug("Checking last header value of field : " + header_field.Name + " with value " + objval + " + with incoming value + " + header_field.Value);
  406. if (objval.ToString() != header_field.Value.ToString())
  407. {
  408. logger.Debug("a different value! we'll save a header then...");
  409. header_updated = true;
  410. break;
  411. }
  412. }
  413. else
  414. {
  415. if (header_field.Value.ToString() != "")
  416. {
  417. logger.Debug("Dunno why, but objval was null." + header_field + " we are going to save a new one.");
  418. header_updated = true;
  419. break;
  420. }
  421. }
  422. }
  423. if (header_updated)
  424. {
  425. logger.Debug("Saving a new header then");
  426. var header = activity_json.Header.ToObject(dbset_header_type);
  427. //now do the saving! -- this works the exact same way for update as it does for new
  428. header.ActivityId = activity.Id;
  429. header.ByUserId = activity.UserId;
  430. header.EffDt = DateTime.Now;
  431. dbset_header.Add(header);
  432. db.SaveChanges();
  433. }
  434. //there are three possible cases of changes:
  435. // 1) updated row (has ID and is in "updatedRowIds" list)
  436. // 2) new row (has no ID)
  437. // 3) deleted row (is not in the list, ID is in "deletedRowIds" list)
  438. //we ALWAYS make such indication by INSERTING a new row with a matching rowid + activityid + new current effective date.
  439. // exception is NEW row which gets and incremented rowid
  440. //first, lets lookup our last row id so we have a place to start if we add rows.
  441. int rowid = 1;
  442. var last_row_list = dbset_detail.SqlQuery("SELECT * FROM " + data_detail_name + " WHERE ActivityId = "+ activity.Id + " AND RowStatusId = " + DataDetail.ROWSTATUS_ACTIVE + " ORDER BY RowId DESC");
  443. //db.AdultWeir_Detail.Where(o => o.ActivityId == activity.Id).Where(o => o.RowStatusId == DataDetail.ROWSTATUS_ACTIVE).OrderByDescending(d => d.RowId).FirstOrDefault();
  444. var last_row = this.getFirstItem(last_row_list);
  445. if (last_row != null)
  446. {
  447. rowid = last_row.RowId+1;
  448. }
  449. else
  450. logger.Debug("Hmm there were no previous details rows for activity : " + activity.Id + " so we are starting at 1.");
  451. //now lets iterate our incoming rows and see what we've got.
  452. var details = new List<DataDetail>();
  453. List<int> updated_rows = new List<int>();
  454. foreach (var updated_row in json.updatedRowIds)
  455. {
  456. logger.Debug("Found an updated row: " + updated_row);
  457. updated_rows.Add(updated_row.ToObject<int>());
  458. }
  459. List<int> deleted_rows = new List<int>();
  460. foreach(var deleted_row in json.deletedRowIds)
  461. {
  462. logger.Debug("Found a deleted row: " + deleted_row);
  463. deleted_rows.Add(deleted_row.ToObject<int>());
  464. if (updated_rows.Contains(deleted_row.ToObject<int>()))
  465. updated_rows.Remove(deleted_row.ToObject<int>());
  466. }
  467. foreach (var detailitem in activity_json.Details)
  468. {
  469. var adw = detailitem.ToObject(dbset_detail_type);
  470. logger.Debug("spinning through incoming details: " + adw.Id);
  471. if (adw.Id == 0)
  472. {
  473. //new record
  474. adw.RowId = rowid; rowid++;
  475. details.Add(adw);
  476. }
  477. else
  478. {
  479. //deleted or updated?
  480. if (updated_rows.Contains(adw.Id))
  481. {
  482. //updated
  483. adw.Id = 0;
  484. details.Add(adw);
  485. }
  486. else if (deleted_rows.Contains(adw.Id))
  487. {
  488. //deleted
  489. adw.Id = 0;
  490. adw.RowStatusId = DataDetail.ROWSTATUS_DELETED;
  491. details.Add(adw);
  492. }
  493. //otherwise nothing.
  494. }
  495. }
  496. foreach (var detail in details)
  497. {
  498. detail.ActivityId = activity.Id;
  499. detail.ByUserId = activity.UserId;
  500. detail.EffDt = DateTime.Now;
  501. //TODO: activity QA ID + comment
  502. dbset_detail.Add(detail);
  503. }
  504. db.SaveChanges();
  505. //If there is a ReadingDateTime field in use, set the activity description to be the range of reading dates for this activity.
  506. if (dataset.Datastore.TablePrefix == "WaterTemp") // others with readingdatetime?
  507. {
  508. using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServicesContext"].ConnectionString))
  509. {
  510. con.Open();
  511. var query = "update Activities set Description = (select concat(convert(varchar,min(ReadingDateTime),111), ' - ', convert(varchar,max(ReadingDateTime),111)) from " + dataset.Datastore.TablePrefix + "_Detail_VW where ActivityId = " + activity.Id + ") where Id = " + activity.Id;
  512. using (SqlCommand cmd = new SqlCommand(query, con))
  513. {
  514. logger.Debug(query);
  515. cmd.ExecuteNonQuery();
  516. }
  517. }
  518. }
  519. }
  520. }
  521. return new HttpResponseMessage(HttpStatusCode.OK);
  522. }
  523. private dynamic getFirstItem(dynamic list)
  524. {
  525. dynamic first = null;
  526. foreach (var item in list)
  527. {
  528. first = item;
  529. break;
  530. }
  531. return first;
  532. }
  533. public HttpResponseMessage SaveDatasetActivities(JObject jsonData)
  534. {
  535. return SaveDatasetActivitiesEFF(jsonData);
  536. }
  537. //so we'll build one that generates sql directly since the EFF way has mediocre performance.
  538. [HttpPost]
  539. private HttpResponseMessage SaveDatasetActivitiesSQL(JObject jsonData)
  540. {
  541. var db = ServicesContext.Current;
  542. User me = AuthorizationManager.getCurrentUser();
  543. dynamic json = jsonData;
  544. Dataset dataset = db.Datasets.Find(json.DatasetId.ToObject<int>());
  545. if (dataset == null)
  546. throw new Exception("Configuration Error.");
  547. Project project = db.Projects.Find(dataset.ProjectId);
  548. if (!project.isOwnerOrEditor(me))
  549. throw new Exception("Authorization error.");
  550. var data_header_name = dataset.Datastore.TablePrefix + "_Header";
  551. var data_detail_name = dataset.Datastore.TablePrefix + "_Detail";
  552. //these will get loaded once and then stay the same every time.
  553. var query_header = "INSERT INTO " + data_header_name + " (";
  554. var query_detail = "INSERT INTO " + data_detail_name + " (";
  555. var headerFields = new List<string>();
  556. var detailFields = new List<string>();
  557. using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ServicesContext"].ConnectionString))
  558. {
  559. con.Open();
  560. foreach (var item in json.activities)
  561. {
  562. int newActivityId = 0;
  563. //each activity in its own scope...
  564. var trans = con.BeginTransaction();
  565. if (item is JProperty)
  566. {
  567. var prop = item as JProperty;
  568. dynamic activity_json = prop.Value;
  569. Activity activity = new Activity();
  570. activity.LocationId = activity_json.LocationId;
  571. try
  572. {
  573. activity.ActivityDate = activity_json.ActivityDate;
  574. }
  575. catch (Exception e)
  576. {
  577. //TODO -- this is a very bad idea if the date is wrong...
  578. logger.Debug("Ooops had an error converting date: " + activity_json.ActivityDate);
  579. logger.Debug(e.ToString());
  580. throw e;
  581. }
  582. activity.DatasetId = json.DatasetId;
  583. activity.UserId = me.Id;
  584. activity.SourceId = 1; // TODO
  585. activity.ActivityTypeId = 1;
  586. activity.CreateDate = DateTime.Now;
  587. activity.InstrumentId = activity_json.InstrumentId;
  588. activity.AccuracyCheckId = activity_json.AccuracyCheckId;
  589. activity.PostAccuracyCheckId = activity_json.PostAccuracyCheckId;
  590. activity.Timezone = (activity_json.Timezone != null) ? activity_json.Timezone.Replace("'","''") : "";
  591. var activity_query = "INSERT INTO Activities (LocationId, ActivityDate, DatasetId, UserId, SourceId, ActivityTypeId, CreateDate, Timezone) VALUES (";
  592. activity_query +=
  593. activity.LocationId + ",'" +
  594. activity.ActivityDate + "'," +
  595. activity.DatasetId + "," +
  596. activity.UserId + "," +
  597. activity.SourceId + "," +
  598. activity.ActivityTypeId + "," +
  599. "'" + activity.CreateDate + "'," +
  600. //activity.InstrumentId + "," +
  601. //activity.AccuracyCheckId + "," +
  602. //activity.PostAccuracyCheckId + "," +
  603. "'" + activity.Timezone + "');";
  604. activity_query += "SELECT SCOPE_IDENTITY();";
  605. logger.Debug(activity_query);
  606. using (SqlCommand cmd = new SqlCommand(activity_query, con,trans))
  607. {
  608. var result = cmd.ExecuteScalar();
  609. //logger.Debug(result + result.GetType().ToString()); = System.Decimal?!
  610. newActivityId = Convert.ToInt32(result.ToString());
  611. }
  612. //db.Activities.Add(activity);
  613. //db.SaveChanges();
  614. dynamic activityqastatus = activity_json.ActivityQAStatus;
  615. activity.Id = newActivityId;
  616. logger.Debug("Hey! we have a new activity id the ol' fashioned way: " + activity.Id);
  617. var newQA_query = "INSERT INTO ActivityQAs (ActivityId, QAStatusId, Comments, EffDt, UserId) VALUES (";
  618. ActivityQA newQA = new ActivityQA();
  619. newQA.ActivityId = newActivityId;
  620. newQA.QAStatusId = activityqastatus.QAStatusID.ToObject<int>();
  621. newQA.Comments = activityqastatus.Comments.Replace("'","''");
  622. newQA.EffDt = DateTime.Now;
  623. newQA.UserId = activity.UserId;
  624. newQA_query += newQA.ActivityId + "," +
  625. newQA.QAStatusId + "," +
  626. "'" + newQA.Comments + "','" +
  627. newQA.EffDt + "'," +
  628. newQA.UserId + ");";
  629. logger.Debug(newQA_query);
  630. using (SqlCommand cmd = new SqlCommand(newQA_query, con, trans))
  631. {
  632. if (cmd.ExecuteNonQuery() == 0)
  633. {
  634. logger.Debug("Failed to execute query: " + newQA_query);
  635. throw new Exception("Failed to execute qa query. See log.");
  636. }
  637. }
  638. //db.ActivityQAs.Add(newQA);
  639. //db.SaveChanges();
  640. //get these ready for a new set of values
  641. var query_header_values = " VALUES (";
  642. var query_detail_values = " VALUES (";
  643. var headerValues = new List<string>();
  644. var detailValues = new List<string>();
  645. //have our headers been populated yet? we only have to do it once.
  646. if (headerFields.Count == 0)
  647. {
  648. //first the ones we always have
  649. headerFields.Add("ActivityId");
  650. headerFields.Add("ByUserId");
  651. headerFields.Add("EffDt");
  652. //now spin through and add any incoming ones from our JSON.
  653. var the_header = activity_json.Header as JObject;
  654. IList<string> propertyNames = the_header.Properties().Select(p => p.Name).ToList();
  655. foreach (var prop_field in propertyNames)
  656. {
  657. headerFields.Add(prop_field);
  658. }
  659. }
  660. headerValues.Add(activity.Id.ToString());
  661. headerValues.Add(activity.UserId.ToString());
  662. headerValues.Add("'" + DateTime.Now.ToString() + "'");
  663. //now populate header values
  664. foreach (var prop_field in headerFields)
  665. {
  666. if (prop_field != "ActivityId" && prop_field != "ByUserId" && prop_field != "EffDt") //these are already done.
  667. {
  668. var control_type = dataset.Fields.Where(o => o.Field.DbColumnName == prop_field).Single().ControlType;
  669. var objVal = activity_json.Header.GetValue(prop_field);
  670. if (objVal == null)
  671. headerValues.Add("null");
  672. else
  673. {
  674. headerValues.Add(getStringValueByControlType(control_type, objVal.ToString()));
  675. }
  676. }
  677. }
  678. var the_query = query_header + string.Join(",", headerFields) + ") " + query_header_values + string.Join(",", headerValues) + ")";
  679. logger.Debug(the_query);
  680. using (SqlCommand cmd = new SqlCommand(the_query, con, trans))
  681. {
  682. if (cmd.ExecuteNonQuery() == 0)
  683. {
  684. logger.Debug("Failed to execute query: " + the_query);
  685. throw new Exception("Failed to execute header query. See log.");
  686. }
  687. }
  688. //---------------- now for the details...
  689. int rowid = 1;
  690. foreach (JObject detail in activity_json.Details)
  691. {
  692. //have our detail fields been populated yet? we only have to do it once.
  693. if (detailFields.Count == 0)
  694. {
  695. //first the ones we always have
  696. detailFields.Add("ActivityId");
  697. detailFields.Add("ByUserId");
  698. detailFields.Add("EffDt");
  699. detailFields.Add("RowStatusId");
  700. detailFields.Add("RowId");
  701. detailFields.Add("QAStatusId");
  702. //now spin through and add any incoming ones from our JSON.
  703. IList<string> propertyNames = detail.Properties().Select(p => p.Name).ToList();
  704. foreach (var prop_field in propertyNames)
  705. {
  706. DatasetField the_field = dataset.Fields.Where(o => o.Field.DbColumnName == prop_field && o.FieldRoleId == 2).SingleOrDefault();
  707. if (the_field != null)
  708. detailFields.Add(prop_field);
  709. }
  710. }
  711. detailValues.Add(activity.Id.ToString());
  712. detailValues.Add(activity.UserId.ToString());
  713. detailValues.Add("'" + DateTime.Now.ToString() + "'");
  714. detailValues.Add(DataDetail.ROWSTATUS_ACTIVE.ToString());
  715. detailValues.Add(rowid.ToString());
  716. detailValues.Add(detail.GetValue("QAStatusId").ToString());
  717. //now populate detail values
  718. foreach (var prop_field in detailFields)
  719. {
  720. if (prop_field != "QAStatusId" && prop_field != "ActivityId" && prop_field != "ByUserId" && prop_field != "EffDt" && prop_field != "RowId" && prop_field != "RowStatusId") //these are already done.
  721. {
  722. var control_type = dataset.Fields.Where(o => o.Field.DbColumnName == prop_field).SingleOrDefault().ControlType;
  723. var objVal = detail.GetValue(prop_field);
  724. if (objVal == null)
  725. detailValues.Add("null");
  726. else
  727. {
  728. detailValues.Add(getStringValueByControlType(control_type, objVal.ToString()));
  729. }
  730. }
  731. }
  732. rowid++;
  733. var the_detail_query = query_detail + string.Join(",", detailFields) + ") " + query_detail_values + string.Join(",", detailValues) + ")";
  734. //logger.Debug(the_detail_query);
  735. using (SqlCommand cmd = new SqlCommand(the_detail_query, con, trans))
  736. {
  737. if (cmd.ExecuteNonQuery() == 0)
  738. {
  739. logger.Debug("Problem executing: " + the_detail_query);
  740. throw new Exception("Failed to execute detail query!");
  741. }
  742. }
  743. detailValues = new List<string>();
  744. }//foreach detail
  745. //If there is a ReadingDateTime field in use, set the activity description to be the range of reading dates for this activity.
  746. if (newActivityId != 0 && dataset.Datastore.TablePrefix == "WaterTemp") // others with readingdatetime?
  747. {
  748. var query = "update Activities set Description = (select concat(convert(varchar,min(ReadingDateTime),111), ' - ', convert(varchar,max(ReadingDateTime),111)) from " + dataset.Datastore.TablePrefix + "_Detail_VW where ActivityId = " + newActivityId + ") where Id = " + newActivityId;
  749. using (SqlCommand cmd = new SqlCommand(query, con))
  750. {
  751. logger.Debug(query);
  752. cmd.ExecuteNonQuery();
  753. }
  754. }
  755. }//if is a jproperty
  756. trans.Commit();
  757. }//foreach activity
  758. }//connection
  759. return new HttpResponseMessage(HttpStatusCode.OK);
  760. }
  761. private string getStringValueByControlType(string control_type, string in_val)
  762. {
  763. string retval = null;
  764. switch (control_type)
  765. {
  766. case "text":
  767. case "textarea":
  768. case "multiselect":
  769. case "select":
  770. case "date":
  771. case "datetime":
  772. retval = "'" + in_val.Replace("'", "''") + "'";
  773. break;
  774. default:
  775. retval = in_val;
  776. break;
  777. }
  778. return retval;
  779. }
  780. [HttpPost]
  781. private HttpResponseMessage SaveDatasetActivitiesEFF(JObject jsonData)
  782. {
  783. logger.Debug("Saving dataset activities: ");
  784. var db = ServicesContext.Current;
  785. User me = AuthorizationManager.getCurrentUser();
  786. dynamic json = jsonData;
  787. //COPY PASTE -- TODO -- reduce code smell!
  788. Dataset dataset = db.Datasets.Find(json.DatasetId.ToObject<int>());
  789. if (dataset == null)
  790. throw new Exception("Configuration Error.");
  791. Project project = db.Projects.Find(dataset.ProjectId);
  792. if (!project.isOwnerOrEditor(me))
  793. throw new Exception("Authorization error.");
  794. //setup our generic data stuff
  795. var data_header_name = dataset.Datastore.TablePrefix + "_Header";
  796. var data_detail_name = dataset.Datastore.TablePrefix + "_Detail";
  797. var dbset_header = db.GetDbSet(data_header_name);
  798. var dbset_detail = db.GetDbSet(data_detail_name);
  799. var dbset_header_type = db.GetTypeFor(data_header_name);
  800. var dbset_detail_type = db.GetTypeFor(data_detail_name);
  801. //var duplicateActivities = new List<Activity>();
  802. var new_records = new List<Activity>();
  803. //wrap this in a transaction
  804. foreach (var item in json.activities)
  805. {
  806. var scope = new TransactionScope(
  807. TransactionScopeOption.RequiresNew,
  808. new TransactionOptions()
  809. {
  810. IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
  811. });
  812. int newActivityId = 0 ;
  813. using (scope)
  814. {
  815. if (item is JProperty)
  816. {
  817. var prop = item as JProperty;
  818. dynamic activity_json = prop.Value;
  819. Activity activity = new Activity();
  820. activity.LocationId = activity_json.LocationId;
  821. try
  822. {
  823. activity.ActivityDate = activity_json.ActivityDate;
  824. }
  825. catch (Exception e)
  826. {
  827. //TODO -- this is a very bad idea if the date is wrong...
  828. logger.Debug("Ooops had an error converting date: " + activity_json.ActivityDate);
  829. logger.Debug(e.ToString());
  830. throw e;
  831. }
  832. try
  833. {
  834. activity.DatasetId = json.DatasetId;
  835. activity.UserId = me.Id;
  836. activity.SourceId = 1; // TODO
  837. activity.ActivityTypeId = 1;
  838. activity.CreateDate = DateTime.Now;
  839. activity.InstrumentId = activity_json.InstrumentId;
  840. activity.AccuracyCheckId = activity_json.AccuracyCheckId;
  841. activity.PostAccuracyCheckId = activity_json.PostAccuracyCheckId;
  842. activity.Timezone = activity_json.Timezone;
  843. logger.Debug("and we have finished parameters.");
  844. /*
  845. //check for duplicates. If it is a duplicate, add it to our list and bail out.
  846. if (activity.isDuplicate())
  847. {
  848. duplicateActivities.Add(activity);
  849. }
  850. */
  851. db.Activities.Add(activity);
  852. db.SaveChanges();
  853. dynamic activityqastatus = activity_json.ActivityQAStatus;
  854. //logger.Debug(activity_json.ActivityQAStatus);
  855. //logger.Debug(activityqastatus.QAStatusId.ToObject<int>());
  856. newActivityId = activity.Id;
  857. ActivityQA newQA = new ActivityQA();
  858. newQA.ActivityId = activity.Id;
  859. newQA.QAStatusId = activityqastatus.QAStatusID.ToObject<int>();
  860. newQA.Comments = activityqastatus.Comments;
  861. newQA.EffDt = DateTime.Now;
  862. newQA.UserId = activity.UserId;
  863. db.ActivityQAs.Add(newQA);
  864. db.SaveChanges();
  865. // logger.Debug("Created a new activity: ");
  866. // logger.Debug(" LocationID = " + activity_json.LocationId);
  867. // logger.Debug(" ActivityDate = " + activity_json.ActivityDate);
  868. // logger.Debug(" ID = " + activity.Id);
  869. var header = activity_json.Header.ToObject(dbset_header_type);
  870. var details = new List<DataDetail>();
  871. foreach (var detailitem in activity_json.Details)
  872. {
  873. details.Add(detailitem.ToObject(dbset_detail_type));
  874. }
  875. //now do the saving!
  876. header.ActivityId = activity.Id;
  877. header.ByUserId = activity.UserId;
  878. header.EffDt = DateTime.Now;
  879. dbset_header.Add(header);
  880. //details
  881. int rowid = 1;
  882. foreach (var detail in details)
  883. {
  884. detail.RowId = rowid;
  885. detail.RowStatusId = DataDetail.ROWSTATUS_ACTIVE;

Large files files are truncated, but you can click here to view the full file