PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Comdiv.DefaultDependencies/Persistence/_______NHibernatePersister.cs

http://comdivmvccontrib.googlecode.com/
C# | 434 lines | 350 code | 82 blank | 2 comment | 56 complexity | dd38fd8f1a44d13c9de33dc1db22e2f5 MD5 | raw file
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using System.Linq;
  6. using Comdiv.SessionEasier;
  7. using log4net;
  8. using NHibernate;
  9. using NHibernate.Criterion;
  10. namespace Comdiv.Model {
  11. public class NHibernatePersister : PersisterBase, INewPersisentObjectCreator, IPersisterInitiator, IPersisterTypeResolver{
  12. private readonly IDictionary<string, Type> resolveCache = new Dictionary<string, Type>();
  13. private bool usePreprocessors = false;
  14. private ILog log = logger.getLogger("NHibernatePersister");
  15. protected IList<IHqlPreprocessor> preprocessors = new List<IHqlPreprocessor>();
  16. public NHibernatePersister() {
  17. Priority = 100;
  18. RealStorage = true;
  19. IsForDefaultPersisterChain = true;
  20. InitializeDefaultInterceptors();
  21. }
  22. protected void InitializeDefaultInterceptors(){
  23. interceptors
  24. .fillFromLocator()
  25. //.ensureInstance(()=>new UidSetInterceptor())
  26. .ensureInstance(()=> new CodeGenerator { Format = "~{sname}" })
  27. .ensureInstance(()=>new UsrAwareGenerator())
  28. ;
  29. preprocessors
  30. .fillFromLocator();
  31. usePreprocessors = preprocessors.Count != 0;
  32. }
  33. protected IDictionary<string, Type> ResolveCache {
  34. get { return resolveCache; }
  35. }
  36. #region INewPersisentObjectCreator Members
  37. public T CreateNew<T>() {
  38. return (T)CreateNew(typeof(T));
  39. }
  40. public object CreateNew(Type type) {
  41. return CreateNew(null, type);
  42. }
  43. #endregion
  44. #region IPersisterInitiator Members
  45. public bool Init() {
  46. return true;
  47. }
  48. #endregion
  49. #region IPersisterTypeResolver Members
  50. public Type Resolve(Type type) {
  51. return Resolve(null, type);
  52. }
  53. #endregion
  54. public object CreateNew(string alias, Type type) {
  55. var realType = Resolve(alias, type);
  56. var result = realType.create();
  57. InterceptNew(result);
  58. return result;
  59. }
  60. object sync = new object();
  61. public Type Resolve(string alias, Type type) {
  62. lock (sync)
  63. {
  64. var key = (alias ?? "") + "_" + type.FullName;
  65. if (!ResolveCache.ContainsKey(key))
  66. {
  67. var registeredClasses = this._<ISessionFactoryProvider>().GetFactory(alias).GetAllClassMetadata();
  68. Type targetType = null;
  69. foreach (var pair in registeredClasses)
  70. {
  71. var testType = pair.Value.GetMappedClass(EntityMode.Poco);
  72. if (testType.Equals(type) || type.IsAssignableFrom(testType) || testType.IsAssignableFrom(type))
  73. {
  74. targetType = testType;
  75. break;
  76. }
  77. }
  78. ResolveCache[key] = targetType;
  79. }
  80. return ResolveCache[key];
  81. }
  82. }
  83. [ThreadStatic]
  84. public static ISession FOR_HACKS_ONLY_SESSION;
  85. private ISession GetSession(string alias){
  86. if (null != FOR_HACKS_ONLY_SESSION) return FOR_HACKS_ONLY_SESSION;
  87. var result = (this._<ISessionProvider>() ?? new DefaultSessionProvider()).GetSession(alias);
  88. if(!result.IsConnected){
  89. result.Reconnect();
  90. }
  91. if(result.Connection.State!=ConnectionState.Open){
  92. result.Connection.Open();
  93. }
  94. return result;
  95. }
  96. protected override void InternalDelete(IPersisterContext context) {
  97. Delete(context.Alias, context.Target, context.Hint.Flush);
  98. }
  99. public virtual void Delete(string alias, object target, bool flush)
  100. {
  101. using (var s = FlushedContext.Create(flush, alias, this))
  102. {
  103. s.Session.Delete(target);
  104. }
  105. }
  106. public override void Exists(IPersisterContext context) {
  107. var session = GetSession(context.Alias);
  108. var type = Resolve(context.Alias, context.TargetType);
  109. var exists = session.CreateCriteria(type, "this");
  110. if (context.PrimaryKey is string && typeof(IWithCode).IsAssignableFrom(type)) {
  111. exists.Add(Restrictions.Eq("Code", context.PrimaryKey));
  112. } else if (context.PrimaryKey is Guid && typeof(IWithUid).IsAssignableFrom(type)) {
  113. exists.Add(Restrictions.Eq("Uid", context.PrimaryKey));
  114. } else {
  115. exists.Add(Restrictions.Eq(Projections.Id(), context.PrimaryKey));
  116. }
  117. exists.SetProjection(Projections.Count(Projections.Id()));
  118. var existedId = exists.UniqueResult<object>();
  119. context.Finish(0 != existedId.toInt());
  120. }
  121. public override bool IsApplyableTo(Type type) {
  122. return IsApplyableTo(null, type);
  123. }
  124. public virtual bool IsApplyableTo(string alias, Type type) {
  125. if (type.Equals(typeof(NHiberanatedType))) return true;
  126. return null != Resolve(alias, type);
  127. }
  128. protected override void InternalLoad(IPersisterContext context) {
  129. if(context.Finished) return;
  130. var type = ResolveType(context);
  131. var session = GetSession(context.Alias);
  132. object result = null;
  133. if (context.PrimaryKey is string && typeof(IWithCode).IsAssignableFrom(type)){
  134. result =
  135. session.CreateCriteria(type, "this").SetMaxResults(1).Add(Restrictions.Eq("Code",
  136. context.PrimaryKey)).
  137. UniqueResult();
  138. }
  139. else if (context.PrimaryKey is string && typeof(IWithName).IsAssignableFrom(type))
  140. {
  141. result =
  142. session.CreateCriteria(type, "this").SetMaxResults(1).Add(Restrictions.Eq("Name",
  143. context.PrimaryKey)).
  144. UniqueResult();
  145. }
  146. else if (context.PrimaryKey is Guid && typeof(IWithUid).IsAssignableFrom(type))
  147. {
  148. result =
  149. session.CreateCriteria(type, "this").SetMaxResults(1).Add(Restrictions.Eq("Uid",
  150. context.PrimaryKey)).
  151. UniqueResult();
  152. }
  153. else
  154. {
  155. result = session.Get(type, context.PrimaryKey);
  156. }
  157. context.Finish(result);
  158. }
  159. protected override void InternalQuery(IPersisterContext context) {
  160. if (context.Finished) return;
  161. var type = ResolveType(context);
  162. var query = context.BaseQuery;
  163. var advancedParameters = context.AdvancedQuery;
  164. var hint = context.Hint;
  165. var alias = context.Alias;
  166. if (context.BaseQuery is ICriteria){
  167. context.FinishQuery(
  168. getByCriteria(alias, (ICriteria)query, type,
  169. advancedParameters.Cast<Order>().ToArray(),
  170. hint)
  171. );
  172. return;
  173. }
  174. if (null == query){
  175. context.FinishQuery(
  176. getOnNullCondition(alias, type, context.Hint)
  177. );
  178. return;
  179. }
  180. if (query is string && advancedParameters.yes() && advancedParameters.Count == 1){
  181. context.FinishQuery(
  182. getByProperty(alias, query as string, type, advancedParameters[0], hint)
  183. );
  184. return;
  185. }
  186. if (query is string){
  187. context.FinishQuery(
  188. getByHql(alias, type, (string)query, context.Hint, advancedParameters)
  189. );
  190. return;
  191. }
  192. if (query is Order[]){
  193. context.FinishQuery(
  194. getByOrdersAndCriterions(alias, (Order[])query, type,
  195. advancedParameters.Cast<ICriterion>().ToArray(),
  196. hint)
  197. );
  198. return;
  199. }
  200. if (query is Order){
  201. context.FinishQuery(
  202. getByOrdersAndCriterions(alias, new[] { (Order)query }, type,
  203. advancedParameters.Cast<ICriterion>().ToArray(), hint)
  204. );
  205. return;
  206. }
  207. if (query is ICriterion) {
  208. var criterions = advancedParameters.OfType<ICriterion>().ToList();
  209. var orders = advancedParameters.OfType<Order>().ToArray();
  210. criterions.Insert(0, query as ICriterion);
  211. context.FinishQuery(
  212. getByOrdersAndCriterions(alias, orders, type, criterions.ToArray(), hint)
  213. );
  214. return;
  215. }
  216. if (query is DetachedCriteria){
  217. context.FinishQuery(
  218. getByDetachedCriteria(alias, (DetachedCriteria)query, type,
  219. advancedParameters.Cast<Order>().ToArray(),
  220. hint)
  221. );
  222. return;
  223. }
  224. context.Throw(new NHibernateException(query, advancedParameters));
  225. }
  226. public override void Refresh(IPersisterContext context) {
  227. if (context.Finished) {
  228. return;
  229. }
  230. GetSession(context.Alias).Refresh(context.Target);
  231. context.Finished = true;
  232. }
  233. protected override void InternalSave(IPersisterContext context) {
  234. Save(context.Alias, context.Target, context.Hint.Flush, context.Hint.Copy);
  235. }
  236. protected override Type ResolveType(IPersisterContext context) {
  237. return Resolve(context.Alias, context.TargetType);
  238. }
  239. protected virtual void Save(string alias, object target, bool flush, bool copy) {
  240. // WARN: ? object ????? ????????? ??? ??? ??????
  241. using (var s = FlushedContext.Create(flush, alias, this)) {
  242. if (copy) {
  243. s.Session.SaveOrUpdateCopy(target);
  244. } else {
  245. s.Session.SaveOrUpdate(target);
  246. }
  247. }
  248. }
  249. private IEnumerable getByHql(string alias, Type type, string query, Hint hint, IList<object> advancedParameters) {
  250. if(log.IsDebugEnabled){
  251. log.Debug("query: "+query+"; params :"+advancedParameters.concat(";"));
  252. }
  253. if(usePreprocessors){
  254. preprocessors.map(x => query = x.Rewrite(query));
  255. if(log.IsDebugEnabled){
  256. log.Debug("reqrited query: "+query);
  257. }
  258. }
  259. var session = GetSession(alias);
  260. var q = "hql" == hint.QueryLanguage.ToLower() ? session.CreateQuery(query) : session.CreateSQLQuery(query);
  261. if(hint.MaxResult!=0){
  262. q.SetMaxResults(hint.MaxResult);
  263. }
  264. int pos = 0;
  265. foreach (var o in advancedParameters) {
  266. q.SetParameter(pos, o);
  267. pos++;
  268. }
  269. var result = q.Enumerable();
  270. return result;
  271. }
  272. private IEnumerable getByDetachedCriteria(string alias, DetachedCriteria criteria, Type realType, Order[] orders,
  273. Hint hint) {
  274. if (hint.MaxResult == 1) {
  275. criteria.SetMaxResults(1);
  276. }
  277. foreach (var order in orders) {
  278. criteria.AddOrder(order);
  279. }
  280. var session = GetSession(alias);
  281. var result = criteria.GetExecutableCriteria(session).List();
  282. return result;
  283. }
  284. private IEnumerable getByCriteria(string alias, ICriteria criteria, Type realType, Order[] orders,
  285. Hint hint) {
  286. if (hint.MaxResult == 1) {
  287. criteria.SetMaxResults(1);
  288. }
  289. foreach (var order in orders) {
  290. criteria.AddOrder(order);
  291. }
  292. var result = criteria.List();
  293. return result;
  294. }
  295. private IEnumerable getByOrdersAndCriterions(string alias, Order[] orders, Type realType,
  296. ICriterion[] criterions, Hint hint) {
  297. var session = GetSession(alias);
  298. var crit = session.CreateCriteria(realType, "this");
  299. if (hint.MaxResult != 0) {
  300. crit.SetMaxResults(hint.MaxResult);
  301. }
  302. foreach (var criterion in (criterions ?? new ICriterion[] { })) {
  303. crit.Add(criterion);
  304. }
  305. foreach (var order in (orders ?? new Order[] { })) {
  306. crit.AddOrder(order);
  307. }
  308. IEnumerable result = null;
  309. try{
  310. result = crit.List();
  311. }catch(NHibernate.ADOException ex){
  312. if (ex.ToString().Contains("aborted"))
  313. {
  314. session.Transaction.Rollback();
  315. session.BeginTransaction();
  316. result = crit.List();
  317. }
  318. else
  319. {
  320. throw;
  321. }
  322. }
  323. return result;
  324. }
  325. private IEnumerable getByProperty(string alias, string property, Type realType, object value, Hint hint) {
  326. return getByOrdersAndCriterions(alias, null, realType, new[] { Restrictions.Eq(property, value) }, hint);
  327. }
  328. private IEnumerable getOnNullCondition(string alias, Type realType, Hint hint) {
  329. return getByOrdersAndCriterions(alias, null, realType, null, hint);
  330. }
  331. #region Nested type: FlushedContext
  332. internal class FlushedContext : IDisposable {
  333. private readonly bool Flush;
  334. public FlushedContext(bool flush, ISession session) {
  335. Flush = flush;
  336. Session = session;
  337. }
  338. public ISession Session { get; set; }
  339. #region IDisposable Members
  340. public void Dispose() {
  341. if (Flush) {
  342. Session.Flush();
  343. }
  344. }
  345. #endregion
  346. public static FlushedContext Create(bool flush, string alias, NHibernatePersister persister) {
  347. return new FlushedContext(flush, persister.GetSession(alias));
  348. }
  349. }
  350. #endregion
  351. }
  352. }