/Code/Foundation.Data.Hibernate/HibernateDataContext.cs

https://github.com/DavidMoore/Foundation · C# · 204 lines · 109 code · 29 blank · 66 comment · 15 complexity · 11ecac06ae3bec8e81179bfee0787517 MD5 · raw file

  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Data.Services;
  5. using System.Linq;
  6. using System.Reflection;
  7. using NHibernate;
  8. namespace Foundation.Data.Hibernate
  9. {
  10. /// <summary>
  11. /// NHibernate reflection data context for use in things like WCF Data Services.
  12. /// </summary>
  13. public class HibernateDataContext : IUpdatable
  14. {
  15. readonly List<object> entityToRemove = new List<object>();
  16. readonly List<object> entityToUpdate = new List<object>();
  17. public virtual ISession Session { get; protected set; }
  18. public HibernateDataContext(ISession session)
  19. {
  20. Session = session;
  21. }
  22. /// <summary>
  23. /// Creates the resource of the given type and belonging to the given container
  24. /// </summary>
  25. /// <param name="containerName">container name to which the resource needs to be added</param>
  26. /// <param name="fullTypeName">full type name i.e. Namespace qualified type name of the resource</param>
  27. /// <returns>object representing a resource of given type and belonging to the given container</returns>
  28. object IUpdatable.CreateResource(string containerName, string fullTypeName)
  29. {
  30. Type t = Type.GetType(fullTypeName, true);
  31. object resource = Activator.CreateInstance(t);
  32. entityToUpdate.Add(resource);
  33. return resource;
  34. }
  35. /// <summary>
  36. /// Gets the resource of the given type that the query points to
  37. /// </summary>
  38. /// <param name="query">query pointing to a particular resource</param>
  39. /// <param name="fullTypeName">full type name i.e. Namespace qualified type name of the resource</param>
  40. /// <returns>object representing a resource of given type and as referenced by the query</returns>
  41. object IUpdatable.GetResource(IQueryable query, string fullTypeName)
  42. {
  43. object resource = null;
  44. foreach (object item in query)
  45. {
  46. if (resource != null)
  47. {
  48. throw new DataServiceException("The query must return a single resource");
  49. }
  50. resource = item;
  51. }
  52. if (resource == null)
  53. throw new DataServiceException(404, "Resource not found");
  54. // fullTypeName can be null for deletes
  55. if (fullTypeName != null && resource.GetType().FullName != fullTypeName)
  56. throw new Exception("Unexpected type for resource");
  57. return resource;
  58. }
  59. /// <summary>
  60. /// Resets the value of the given resource to its default value
  61. /// </summary>
  62. /// <param name="resource">resource whose value needs to be reset</param>
  63. /// <returns>same resource with its value reset</returns>
  64. public object ResetResource(object resource)
  65. {
  66. return resource;
  67. }
  68. /// <summary>
  69. /// Sets the value of the given property on the target object
  70. /// </summary>
  71. /// <param name="targetResource">target object which defines the property</param>
  72. /// <param name="propertyName">name of the property whose value needs to be updated</param>
  73. /// <param name="propertyValue">value of the property</param>
  74. public void SetValue(object targetResource, string propertyName, object propertyValue)
  75. {
  76. PropertyInfo propertyInfo = targetResource.GetType().GetProperty(propertyName);
  77. propertyInfo.SetValue(targetResource, propertyValue, null);
  78. if (!entityToUpdate.Contains(targetResource))
  79. entityToUpdate.Add(targetResource);
  80. }
  81. /// <summary>
  82. /// Gets the value of the given property on the target object
  83. /// </summary>
  84. /// <param name="targetResource">target object which defines the property</param>
  85. /// <param name="propertyName">name of the property whose value needs to be updated</param>
  86. /// <returns>the value of the property for the given target resource</returns>
  87. public object GetValue(object targetResource, string propertyName)
  88. {
  89. PropertyInfo propertyInfo = targetResource.GetType().GetProperty(propertyName);
  90. return propertyInfo.GetValue(targetResource, null);
  91. }
  92. /// <summary>
  93. /// Sets the value of the given reference property on the target object
  94. /// </summary>
  95. /// <param name="targetResource">target object which defines the property</param>
  96. /// <param name="propertyName">name of the property whose value needs to be updated</param>
  97. /// <param name="propertyValue">value of the property</param>
  98. public void SetReference(object targetResource, string propertyName, object propertyValue)
  99. {
  100. ((IUpdatable) this).SetValue(targetResource, propertyName, propertyValue);
  101. }
  102. /// <summary>
  103. /// Adds the given value to the collection
  104. /// </summary>
  105. /// <param name="targetResource">target object which defines the property</param>
  106. /// <param name="propertyName">name of the property whose value needs to be updated</param>
  107. /// <param name="resourceToBeAdded">value of the property which needs to be added</param>
  108. public void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
  109. {
  110. PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
  111. if (pi == null)
  112. throw new Exception("Can't find property");
  113. var collection = (IList) pi.GetValue(targetResource, null);
  114. collection.Add(resourceToBeAdded);
  115. if (!entityToUpdate.Contains(targetResource))
  116. entityToUpdate.Add(targetResource);
  117. }
  118. /// <summary>
  119. /// Removes the given value from the collection
  120. /// </summary>
  121. /// <param name="targetResource">target object which defines the property</param>
  122. /// <param name="propertyName">name of the property whose value needs to be updated</param>
  123. /// <param name="resourceToBeRemoved">value of the property which needs to be removed</param>
  124. public void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
  125. {
  126. PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
  127. if (pi == null)
  128. throw new Exception("Can't find property");
  129. var collection = (IList) pi.GetValue(targetResource, null);
  130. collection.Remove(resourceToBeRemoved);
  131. if (!entityToUpdate.Contains(targetResource))
  132. entityToUpdate.Add(targetResource);
  133. }
  134. /// <summary>
  135. /// Delete the given resource
  136. /// </summary>
  137. /// <param name="targetResource">resource that needs to be deleted</param>
  138. public void DeleteResource(object targetResource)
  139. {
  140. entityToRemove.Add(targetResource);
  141. }
  142. /// <summary>
  143. /// Saves all the pending changes made till now
  144. /// </summary>
  145. public void SaveChanges()
  146. {
  147. using (ITransaction transaction = Session.BeginTransaction())
  148. {
  149. Session.FlushMode = FlushMode.Commit;
  150. foreach (object entity in entityToUpdate)
  151. {
  152. Session.SaveOrUpdate(entity);
  153. }
  154. foreach (object entity in entityToRemove)
  155. {
  156. Session.Delete(entity);
  157. }
  158. transaction.Commit();
  159. }
  160. }
  161. /// <summary>
  162. /// Returns the actual instance of the resource represented by the given resource object
  163. /// </summary>
  164. /// <param name="resource">object representing the resource whose instance needs to be fetched</param>
  165. /// <returns>The actual instance of the resource represented by the given resource object</returns>
  166. public object ResolveResource(object resource)
  167. {
  168. return resource;
  169. }
  170. /// <summary>
  171. /// Revert all the pending changes.
  172. /// </summary>
  173. public void ClearChanges() {}
  174. }
  175. }