PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/NHibernate.Shards/src/NHibernate.Shards/Session/ShardedSessionFactoryImpl.cs

https://bitbucket.org/dabide/nhcontrib
C# | 1086 lines | 575 code | 119 blank | 392 comment | 17 complexity | 7d85d029f7aa354e0b242f5cb0d7d128 MD5 | raw file
Possible License(s): BSD-3-Clause, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Apache-2.0, LGPL-3.0, LGPL-2.1
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Collections.ObjectModel;
  5. using System.Data;
  6. using System.Linq;
  7. using Iesi.Collections;
  8. using Iesi.Collections.Generic;
  9. using log4net;
  10. using NHibernate.Cache;
  11. using NHibernate.Cfg;
  12. using NHibernate.Connection;
  13. using NHibernate.Context;
  14. using NHibernate.Dialect.Function;
  15. using NHibernate.Engine;
  16. using NHibernate.Engine.Query;
  17. using NHibernate.Event;
  18. using NHibernate.Exceptions;
  19. using NHibernate.Hql;
  20. using NHibernate.Id;
  21. using NHibernate.Metadata;
  22. using NHibernate.Persister.Collection;
  23. using NHibernate.Persister.Entity;
  24. using NHibernate.Proxy;
  25. using NHibernate.Shards.Criteria;
  26. using NHibernate.Shards.Engine;
  27. using NHibernate.Shards.Id;
  28. using NHibernate.Shards.Strategy;
  29. using NHibernate.Shards.Util;
  30. using NHibernate.Stat;
  31. using NHibernate.Transaction;
  32. using NHibernate.Type;
  33. namespace NHibernate.Shards.Session
  34. {
  35. public class ShardedSessionFactoryImpl : IShardedSessionFactoryImplementor, IControlSessionProvider
  36. {
  37. // the id of the control shard
  38. private static readonly int CONTROL_SHARD_ID = 0;
  39. // the SessionFactoryImplementor objects to which we delegate
  40. private readonly IList<ISessionFactoryImplementor> sessionFactories;
  41. // All classes that cannot be directly saved
  42. private readonly Set<System.Type> classesWithoutTopLevelSaveSupport;
  43. // map of SessionFactories used by this ShardedSessionFactory (might be a subset of all SessionFactories)
  44. private readonly Dictionary<ISessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap;
  45. // map of all existing SessionFactories, used when creating a new ShardedSessionFactory for some subset of shards
  46. private readonly IDictionary<ISessionFactoryImplementor, Set<ShardId>> fullSessionFactoryShardIdMap;
  47. // The strategy we use for all shard-related operations
  48. private readonly IShardStrategy shardStrategy;
  49. // Reference to the SessionFactory we use for functionality that expects
  50. // data to live in a single, well-known location (like distributed sequences)
  51. private readonly ISessionFactoryImplementor controlSessionFactory;
  52. // flag to indicate whether we should do full cross-shard relationship
  53. // checking (very slow)
  54. private readonly bool checkAllAssociatedObjectsForDifferentShards;
  55. // Statistics aggregated across all contained SessionFactories
  56. private readonly IStatistics statistics = new StatisticsImpl();
  57. // our lovely logger
  58. private readonly ILog log = LogManager.GetLogger(typeof(ShardedSessionFactoryImpl));
  59. #region Ctor
  60. /// <summary>
  61. /// Constructs a ShardedSessionFactoryImpl
  62. /// </summary>
  63. /// <param name="shardIds"> The ids of the shards with which this SessionFactory should be associated.</param>
  64. /// <param name="sessionFactoryShardIdMap">Mapping of SessionFactories to shard ids.
  65. /// When using virtual shards, this map associates SessionFactories (physical
  66. /// shards) with virtual shards (shard ids). Map cannot be empty.
  67. /// Map keys cannot be null. Map values cannot be null or empty.</param>
  68. /// <param name="shardStrategyFactory">factory that knows how to create the <see cref="IShardStrategy"/>
  69. /// that will be used for all shard-related operations</param>
  70. /// <param name="classesWithoutTopLevelSaveSupport"> All classes that cannot be saved
  71. /// as top-level objects</param>
  72. /// <param name="checkAllAssociatedObjectsForDifferentShards">Flag that controls
  73. /// whether or not we do full cross-shard relationshp checking (very slow)</param>
  74. public ShardedSessionFactoryImpl(
  75. ICollection<ShardId> shardIds,
  76. IDictionary<ISessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap,
  77. IShardStrategyFactory shardStrategyFactory,
  78. ISet<System.Type> classesWithoutTopLevelSaveSupport,
  79. bool checkAllAssociatedObjectsForDifferentShards)
  80. {
  81. Preconditions.CheckNotNull(sessionFactoryShardIdMap);
  82. Preconditions.CheckArgument(!(sessionFactoryShardIdMap.Count == 0));
  83. Preconditions.CheckNotNull(shardStrategyFactory);
  84. Preconditions.CheckNotNull(classesWithoutTopLevelSaveSupport);
  85. sessionFactories = new List<ISessionFactoryImplementor>(sessionFactoryShardIdMap.Keys);
  86. this.sessionFactoryShardIdMap = new Dictionary<ISessionFactoryImplementor, Set<ShardId>>();
  87. fullSessionFactoryShardIdMap = sessionFactoryShardIdMap;
  88. this.classesWithoutTopLevelSaveSupport = new HashedSet<System.Type>(classesWithoutTopLevelSaveSupport);
  89. this.checkAllAssociatedObjectsForDifferentShards = checkAllAssociatedObjectsForDifferentShards;
  90. Set<ShardId> uniqueShardIds = new HashedSet<ShardId>();
  91. ISessionFactoryImplementor controlSessionFactoryToSet = null;
  92. foreach (var entry in sessionFactoryShardIdMap)
  93. {
  94. ISessionFactoryImplementor implementor = entry.Key;
  95. Preconditions.CheckNotNull(implementor);
  96. Set<ShardId> shardIdSet = entry.Value;
  97. Preconditions.CheckNotNull(shardIdSet);
  98. Preconditions.CheckState(!(shardIdSet.Count == 0));
  99. foreach (ShardId shardId in shardIdSet)
  100. {
  101. //TODO: we should change it so we specify control shard in configuration
  102. if (shardId.Id == CONTROL_SHARD_ID)
  103. {
  104. controlSessionFactoryToSet = implementor;
  105. }
  106. if (!uniqueShardIds.Add(shardId))
  107. {
  108. string msg = string.Format("Cannot have more than one shard with shard id {0}.", shardId.Id);
  109. log.Error(msg);
  110. throw new HibernateException(msg);
  111. }
  112. if (shardIds.Contains(shardId))
  113. {
  114. if (!this.sessionFactoryShardIdMap.ContainsKey(implementor))
  115. this.sessionFactoryShardIdMap.Add(implementor, new HashedSet<ShardId>());
  116. this.sessionFactoryShardIdMap[implementor].Add(shardId);
  117. }
  118. }
  119. }
  120. // make sure someone didn't associate a session factory with a shard id
  121. // that isn't in the full list of shards
  122. foreach (ShardId shardId in shardIds)
  123. {
  124. Preconditions.CheckState(uniqueShardIds.Contains(shardId));
  125. }
  126. controlSessionFactory = controlSessionFactoryToSet;
  127. // now that we have all our shard ids, construct our shard strategy
  128. shardStrategy = shardStrategyFactory.NewShardStrategy(shardIds);
  129. SetupIdGenerators();
  130. }
  131. /// <summary>
  132. /// Constructs a ShardedSessionFactoryImpl
  133. /// </summary>
  134. /// <param name="sessionFactoryShardIdMap">Mapping of SessionFactories to shard ids.
  135. /// When using virtual shards, this map associates SessionFactories (physical
  136. /// shards) with virtual shards (shard ids). Map cannot be empty.
  137. /// Map keys cannot be null. Map values cannot be null or empty.</param>
  138. /// <param name="shardStrategyFactory">factory that knows how to create the <see cref="IShardStrategy"/>
  139. /// that will be used for all shard-related operations</param>
  140. /// <param name="classesWithoutTopLevelSaveSupport">All classes that cannot be saved
  141. /// as top-level objects</param>
  142. /// <param name="checkAllAssociatedObjectsForDifferentShards">Flag that controls
  143. ///whether or not we do full cross-shard relationshp checking (very slow)</param>
  144. public ShardedSessionFactoryImpl(
  145. IDictionary<ISessionFactoryImplementor, Set<ShardId>> sessionFactoryShardIdMap,
  146. IShardStrategyFactory shardStrategyFactory,
  147. ISet<System.Type> classesWithoutTopLevelSaveSupport,
  148. bool checkAllAssociatedObjectsForDifferentShards)
  149. : this(new List<ShardId>(sessionFactoryShardIdMap.Values.Concatenation().Cast<ShardId>()),
  150. sessionFactoryShardIdMap,
  151. shardStrategyFactory,
  152. classesWithoutTopLevelSaveSupport,
  153. checkAllAssociatedObjectsForDifferentShards)
  154. {
  155. }
  156. /**
  157. * Sets the {@link ControlSessionProvider} on id generators that implement the
  158. * {@link GeneratorRequiringControlSessionProvider} interface
  159. */
  160. private void SetupIdGenerators()
  161. {
  162. foreach (ISessionFactoryImplementor sfi in sessionFactories)
  163. {
  164. foreach (IClassMetadata obj in sfi.GetAllClassMetadata().Values)
  165. {
  166. var cmd = obj;
  167. IEntityPersister ep = sfi.GetEntityPersister(cmd.EntityName);
  168. if (ep is IGeneratorRequiringControlSessionProvider)
  169. {
  170. ((IGeneratorRequiringControlSessionProvider)ep.IdentifierGenerator).SetControlSessionProvider(this);
  171. }
  172. }
  173. }
  174. }
  175. #endregion
  176. private ISessionFactoryImplementor AnyFactory
  177. {
  178. get { return sessionFactories[0]; }
  179. }
  180. /// <summary>
  181. /// This collections allows external libraries
  182. /// to add their own configuration to the NHibernate session factory.
  183. /// This is needed in such cases where the library is tightly coupled to NHibernate, such
  184. /// as the case of NHibernate Search
  185. /// </summary>
  186. public IDictionary Items
  187. {
  188. get
  189. {
  190. throw new NotImplementedException();
  191. //return AnyFactory.Items;
  192. }
  193. }
  194. /// <summary>
  195. /// Is outerjoin fetching enabled?
  196. /// </summary>
  197. public bool IsOuterJoinedFetchEnabled
  198. {
  199. get { throw new NotImplementedException(); }
  200. }
  201. /// <summary>
  202. /// Are scrollable <c>ResultSet</c>s supported?
  203. /// </summary>
  204. public bool IsScrollableResultSetsEnabled
  205. {
  206. get { throw new NotImplementedException(); }
  207. }
  208. /// <summary>
  209. /// Is <c>PreparedStatement.getGeneratedKeys</c> supported (Java-specific?)
  210. /// </summary>
  211. public bool IsGetGeneratedKeysEnabled
  212. {
  213. get { throw new NotImplementedException(); }
  214. }
  215. /// <summary>
  216. /// Get the database schema specified in <c>default_schema</c>
  217. /// </summary>
  218. public string DefaultSchema
  219. {
  220. get { throw new NotImplementedException(); }
  221. }
  222. /// <summary>
  223. /// Maximum depth of outer join fetching
  224. /// </summary>
  225. public int MaximumFetchDepth
  226. {
  227. get
  228. {
  229. throw new NotImplementedException();
  230. //return AnyFactory.MaximumFetchDepth;
  231. }
  232. }
  233. /// <summary>
  234. /// Is query caching enabled?
  235. /// </summary>
  236. public bool IsQueryCacheEnabled
  237. {
  238. get
  239. {
  240. throw new NotImplementedException();
  241. //return AnyFactory.IsQueryCacheEnabled;
  242. }
  243. }
  244. /// <summary>
  245. /// Gets the IsolationLevel an IDbTransaction should be set to.
  246. /// </summary>
  247. /// <remarks>
  248. /// This is only applicable to manually controlled NHibernate Transactions.
  249. /// </remarks>
  250. public IsolationLevel Isolation
  251. {
  252. get
  253. {
  254. throw new NotImplementedException();
  255. //return AnyFactory.Isolation;
  256. }
  257. }
  258. public EventListeners EventListeners
  259. {
  260. get { throw new NotImplementedException(); }
  261. }
  262. #region IControlSessionProvider Members
  263. /// <summary>
  264. /// Opens control session.
  265. /// </summary>
  266. /// <returns>control session</returns>
  267. public ISessionImplementor OpenControlSession()
  268. {
  269. Preconditions.CheckState(controlSessionFactory != null);
  270. ISession session = controlSessionFactory.OpenSession();
  271. return (ISessionImplementor)session;
  272. }
  273. #endregion
  274. #region IShardedSessionFactoryImplementor Members
  275. public IDictionary<ISessionFactoryImplementor, Set<ShardId>> GetSessionFactoryShardIdMap()
  276. {
  277. return sessionFactoryShardIdMap;
  278. }
  279. public bool ContainsFactory(ISessionFactoryImplementor factory)
  280. {
  281. return sessionFactories.Contains(factory);
  282. }
  283. /// <summary>
  284. /// All an unmodifiable list of the <see cref="ISessionFactory"/> objects contained within.
  285. /// </summary>
  286. public IList<ISessionFactory> SessionFactories
  287. {
  288. get { return new ReadOnlyCollection<ISessionFactory>((IList<ISessionFactory>) this.sessionFactories); }
  289. }
  290. /// <summary>
  291. /// This method is provided to allow a client to work on a subset of
  292. /// shards or a specialized <see cref="IShardStrategyFactory"/>. By providing
  293. /// the desired shardIds, the client can limit operations to these shards.
  294. /// Alternatively, this method can be used to create a ShardedSessionFactory
  295. /// with different strategies that might be appropriate for a specific operation.
  296. ///
  297. /// The factory returned will not be stored as one of the factories that would
  298. /// be returned by a call to getSessionFactories.
  299. /// </summary>
  300. /// <param name="shardIds"></param>
  301. /// <param name="shardStrategyFactory"></param>
  302. /// <returns>specially configured ShardedSessionFactory</returns>
  303. public IShardedSessionFactory GetSessionFactory(IList<ShardId> shardIds, IShardStrategyFactory shardStrategyFactory)
  304. {
  305. return new SubsetShardedSessionFactoryImpl(
  306. shardIds,
  307. fullSessionFactoryShardIdMap,
  308. shardStrategyFactory,
  309. classesWithoutTopLevelSaveSupport,
  310. checkAllAssociatedObjectsForDifferentShards);
  311. }
  312. /// <summary>
  313. /// Create database connection(s) and open a ShardedSession on it,
  314. /// specifying an interceptor.
  315. /// </summary>
  316. /// <param name="interceptor">a session-scoped interceptor</param>
  317. /// <returns></returns>
  318. /// Throws <see cref="HibernateException"/>
  319. IShardedSession IShardedSessionFactory.OpenSession(IInterceptor interceptor)
  320. {
  321. return new ShardedSessionImpl(
  322. interceptor,
  323. this,
  324. shardStrategy,
  325. classesWithoutTopLevelSaveSupport,
  326. checkAllAssociatedObjectsForDifferentShards);
  327. }
  328. /// <summary>
  329. /// Create database connection(s) and open a ShardedSession on it.
  330. /// </summary>
  331. /// <returns></returns>
  332. /// Throws <see cref="HibernateException"/>
  333. public IShardedSession OpenSession()
  334. {
  335. return new ShardedSessionImpl(this,
  336. shardStrategy,
  337. classesWithoutTopLevelSaveSupport,
  338. checkAllAssociatedObjectsForDifferentShards);
  339. }
  340. /// <summary>
  341. /// Open a <c>ISession</c> on the given connection
  342. /// </summary>
  343. /// <param name="conn">A connection provided by the application</param>
  344. /// <returns>A session</returns>
  345. /// <remarks>
  346. /// Note that the second-level cache will be disabled if you
  347. /// supply a ADO.NET connection. NHibernate will not be able to track
  348. /// any statements you might have executed in the same transaction.
  349. /// Consider implementing your own <see cref="IConnectionProvider" />.
  350. /// </remarks>
  351. public ISession OpenSession(IDbConnection conn)
  352. {
  353. throw new NotSupportedException("Cannot open a sharded session with a user provided connection.");
  354. }
  355. /// <summary>
  356. /// Create database connection and open a <c>ISession</c> on it, specifying an interceptor
  357. /// Warning: this interceptor will be shared across all shards, so be very
  358. /// careful about using a stateful implementation.
  359. /// </summary>
  360. /// <param name="interceptor">A session-scoped interceptor</param>
  361. /// <returns>A session</returns>
  362. public ISession OpenSession(IInterceptor interceptor)
  363. {
  364. return
  365. new ShardedSessionImpl(interceptor,
  366. this,
  367. shardStrategy,
  368. classesWithoutTopLevelSaveSupport,
  369. checkAllAssociatedObjectsForDifferentShards);
  370. }
  371. public ISession OpenSession(IDbConnection conn, IInterceptor interceptor)
  372. {
  373. throw new NotSupportedException("Cannot open a sharded session with a user provided connection.");
  374. }
  375. /// <summary>
  376. /// Create a database connection and open a <c>ISession</c> on it
  377. /// </summary>
  378. /// <returns></returns>
  379. ISession ISessionFactory.OpenSession()
  380. {
  381. return new ShardedSessionImpl(this,
  382. shardStrategy,
  383. classesWithoutTopLevelSaveSupport,
  384. checkAllAssociatedObjectsForDifferentShards);
  385. }
  386. /// <summary>
  387. /// Get the <c>ClassMetadata</c> associated with the given entity class
  388. /// </summary>
  389. /// <param name="persistentType"></param>
  390. /// <returns></returns>
  391. public IClassMetadata GetClassMetadata(System.Type persistentType)
  392. {
  393. // assumption is that all session factories are configured the same way,
  394. // so it doesn't matter which session factory answers this question
  395. return AnyFactory.GetClassMetadata(persistentType);
  396. }
  397. public IClassMetadata GetClassMetadata(string entityName)
  398. {
  399. // assumption is that all session factories are configured the same way,
  400. // so it doesn't matter which session factory answers this question
  401. return AnyFactory.GetClassMetadata(entityName);
  402. }
  403. /// <summary>
  404. /// Get the <c>CollectionMetadata</c> associated with the named collection role
  405. /// </summary>
  406. /// <param name="roleName"></param>
  407. /// <returns></returns>
  408. public ICollectionMetadata GetCollectionMetadata(string roleName)
  409. {
  410. // assumption is that all session factories are configured the same way,
  411. // so it doesn't matter which session factory answers this question
  412. return AnyFactory.GetCollectionMetadata(roleName);
  413. }
  414. IDictionary<string, IClassMetadata> ISessionFactory.GetAllClassMetadata()
  415. {
  416. // assumption is that all session factories are configured the same way,
  417. // so it doesn't matter which session factory answers this question
  418. return AnyFactory.GetAllClassMetadata();
  419. }
  420. IDictionary<string, ICollectionMetadata> ISessionFactory.GetAllCollectionMetadata()
  421. {
  422. // assumption is that all session factories are configured the same way,
  423. // so it doesn't matter which session factory answers this question
  424. return AnyFactory.GetAllCollectionMetadata();
  425. }
  426. /// <summary>
  427. /// Destroy this <c>SessionFactory</c> and release all resources
  428. /// connection pools, etc). It is the responsibility of the application
  429. /// to ensure that there are no open <c>Session</c>s before calling
  430. /// <c>close()</c>.
  431. /// </summary>
  432. public virtual void Close()
  433. {
  434. sessionFactories.Each(sf => sf.Close());
  435. sessionFactories.Clear();
  436. if (classesWithoutTopLevelSaveSupport != null)
  437. classesWithoutTopLevelSaveSupport.Clear();
  438. if (sessionFactoryShardIdMap != null)
  439. sessionFactoryShardIdMap.Clear();
  440. if (fullSessionFactoryShardIdMap != null)
  441. fullSessionFactoryShardIdMap.Clear();
  442. //TODO: to enable statistics see this
  443. //statistics.Clear();
  444. }
  445. /// <summary>
  446. /// Evict all entries from the process-level cache. This method occurs outside
  447. /// of any transaction; it performs an immediate "hard" remove, so does not respect
  448. /// any transaction isolation semantics of the usage strategy. Use with care.
  449. /// </summary>
  450. /// <param name="persistentClass"></param>
  451. public void Evict(System.Type persistentClass)
  452. {
  453. foreach (ISessionFactoryImplementor factory in sessionFactories)
  454. {
  455. factory.Evict(persistentClass);
  456. }
  457. }
  458. /// <summary>
  459. /// Evict an entry from the process-level cache. This method occurs outside
  460. /// of any transaction; it performs an immediate "hard" remove, so does not respect
  461. /// any transaction isolation semantics of the usage strategy. Use with care.
  462. /// </summary>
  463. /// <param name="persistentClass"></param>
  464. /// <param name="id"></param>
  465. public void Evict(System.Type persistentClass, object id)
  466. {
  467. foreach (ISessionFactoryImplementor factory in sessionFactories)
  468. {
  469. factory.Evict(persistentClass, id);
  470. }
  471. }
  472. /// <summary>
  473. /// Evict all entries from the second-level cache. This method occurs outside
  474. /// of any transaction; it performs an immediate "hard" remove, so does not respect
  475. /// any transaction isolation semantics of the usage strategy. Use with care.
  476. /// </summary>
  477. public void EvictEntity(string entityName)
  478. {
  479. foreach (ISessionFactoryImplementor factory in sessionFactories)
  480. {
  481. factory.EvictEntity(entityName);
  482. }
  483. }
  484. public void EvictEntity(string entityName, object id)
  485. {
  486. foreach (ISessionFactory sf in sessionFactories)
  487. {
  488. sf.EvictEntity(entityName, id);
  489. }
  490. }
  491. /// <summary>
  492. /// Evict all entries from the process-level cache. This method occurs outside
  493. /// of any transaction; it performs an immediate "hard" remove, so does not respect
  494. /// any transaction isolation semantics of the usage strategy. Use with care.
  495. /// </summary>
  496. /// <param name="roleName"></param>
  497. public void EvictCollection(string roleName)
  498. {
  499. foreach (ISessionFactoryImplementor factory in sessionFactories)
  500. {
  501. factory.EvictCollection(roleName);
  502. }
  503. }
  504. /// <summary>
  505. /// Evict an entry from the process-level cache. This method occurs outside
  506. /// of any transaction; it performs an immediate "hard" remove, so does not respect
  507. /// any transaction isolation semantics of the usage strategy. Use with care.
  508. /// </summary>
  509. /// <param name="roleName"></param>
  510. /// <param name="id"></param>
  511. public void EvictCollection(string roleName, object id)
  512. {
  513. foreach (ISessionFactoryImplementor factory in sessionFactories)
  514. {
  515. factory.EvictCollection(roleName, id);
  516. }
  517. }
  518. /// <summary>
  519. /// Evict any query result sets cached in the default query cache region.
  520. /// </summary>
  521. public void EvictQueries()
  522. {
  523. foreach (ISessionFactoryImplementor factory in sessionFactories)
  524. {
  525. factory.EvictQueries();
  526. }
  527. }
  528. /// <summary>
  529. /// Evict any query result sets cached in the named query cache region.
  530. /// </summary>
  531. /// <param name="cacheRegion"></param>
  532. public void EvictQueries(string cacheRegion)
  533. {
  534. foreach (ISessionFactoryImplementor factory in sessionFactories)
  535. {
  536. factory.EvictQueries(cacheRegion);
  537. }
  538. }
  539. /// <summary>
  540. /// Get the <see cref="IConnectionProvider" /> used.
  541. /// </summary>
  542. public IConnectionProvider ConnectionProvider
  543. {
  544. // assumption is that all session factories are configured the same way,
  545. // so it doesn't matter which session factory answers this question
  546. get { return AnyFactory.ConnectionProvider; }
  547. }
  548. public string TryGetGuessEntityName(System.Type implementor)
  549. {
  550. throw new NotImplementedException();
  551. }
  552. /// <summary>
  553. /// Get the SQL <c>Dialect</c>
  554. /// </summary>
  555. public Dialect.Dialect Dialect
  556. {
  557. // assumption is that all session factories are configured the same way,
  558. // so it doesn't matter which session factory answers this question
  559. get { return AnyFactory.Dialect; }
  560. }
  561. public IInterceptor Interceptor
  562. {
  563. // assumption is that all session factories are configured the same way,
  564. // so it doesn't matter which session factory answers this question
  565. get { return AnyFactory.Interceptor; }
  566. }
  567. public bool IsClosed
  568. {
  569. get
  570. {
  571. // a ShardedSessionFactory is closed if any of its SessionFactories are closed
  572. foreach (ISessionFactory sf in sessionFactories)
  573. {
  574. if (sf.IsClosed)
  575. return true;
  576. }
  577. return false;
  578. }
  579. }
  580. /// <summary>
  581. /// Obtain a set of the names of all filters defined on this SessionFactory.
  582. /// </summary>
  583. /// <return>The set of filter names.</return>
  584. public ICollection<string> DefinedFilterNames
  585. {
  586. // assumption is that all session factories are configured the same way,
  587. // so it doesn't matter which session factory answers this question
  588. get { return AnyFactory.DefinedFilterNames; }
  589. }
  590. /// <summary>
  591. /// Obtain the definition of a filter by name.
  592. /// </summary>
  593. /// <param name="filterName">The name of the filter for which to obtain the definition.</param>
  594. /// <return>The filter definition.</return>
  595. public FilterDefinition GetFilterDefinition(string filterName)
  596. {
  597. // assumption is that all session factories are configured the same way,
  598. // so it doesn't matter which session factory answers this question
  599. return AnyFactory.GetFilterDefinition(filterName);
  600. }
  601. public Settings Settings
  602. {
  603. // assumption is that all session factories are configured the same way,
  604. // so it doesn't matter which session factory answers this question
  605. get { return AnyFactory.Settings; }
  606. }
  607. /// <summary>
  608. /// Unsupported
  609. /// </summary>
  610. public ISession GetCurrentSession()
  611. {
  612. throw new NotSupportedException();
  613. }
  614. /// <summary> Get a new stateless session.</summary>
  615. public IStatelessSession OpenStatelessSession()
  616. {
  617. throw new NotSupportedException();
  618. }
  619. /// <summary> Get a new stateless session for the given ADO.NET connection.</summary>
  620. public IStatelessSession OpenStatelessSession(IDbConnection connection)
  621. {
  622. throw new NotSupportedException("Cannot open a stateless sharded session with a user provided connection");
  623. }
  624. /// <summary> Get the statistics for this session factory</summary>
  625. public IStatistics Statistics
  626. {
  627. get { return statistics; }
  628. }
  629. ///<summary>
  630. ///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
  631. ///</summary>
  632. ///<filterpriority>2</filterpriority>
  633. public void Dispose()
  634. {
  635. // try to be helpful to apps that don't clean up properly
  636. if (!this.IsClosed)
  637. {
  638. try
  639. {
  640. this.Close();
  641. }
  642. catch (Exception e)
  643. {
  644. this.log.Warn("Caught exception trying to close.", e);
  645. }
  646. }
  647. }
  648. IDictionary<string, ICache> ISessionFactoryImplementor.GetAllSecondLevelCacheRegions()
  649. {
  650. return AnyFactory.GetAllSecondLevelCacheRegions();
  651. }
  652. /// <summary>
  653. /// Get the persister for the named class
  654. /// </summary>
  655. /// <param name="className">The name of the class that is persisted.</param>
  656. /// <returns>The <see cref="IEntityPersister"/> for the class.</returns>
  657. /// <exception cref="MappingException">If no <see cref="IEntityPersister"/> can be found.</exception>
  658. public IEntityPersister GetEntityPersister(string className)
  659. {
  660. // assumption is that all session factories are configured the same way,
  661. // so it doesn't matter which session factory answers this question
  662. return AnyFactory.GetEntityPersister(className);
  663. }
  664. /// <summary>
  665. /// Get the persister object for a collection role
  666. /// </summary>
  667. /// <param name="role"></param>
  668. /// <returns></returns>
  669. public ICollectionPersister GetCollectionPersister(string role)
  670. {
  671. // assumption is that all session factories are configured the same way,
  672. // so it doesn't matter which session factory answers this question
  673. return AnyFactory.GetCollectionPersister(role);
  674. }
  675. /// <summary>
  676. /// Get the return types of a query
  677. /// </summary>
  678. /// <param name="queryString"></param>
  679. /// <returns></returns>
  680. public IType[] GetReturnTypes(string queryString)
  681. {
  682. return AnyFactory.GetReturnTypes(queryString);
  683. }
  684. /// <summary> Get the return aliases of a query</summary>
  685. public string[] GetReturnAliases(string queryString)
  686. {
  687. // assumption is that all session factories are configured the same way,
  688. // so it doesn't matter which session factory answers this question
  689. return AnyFactory.GetReturnAliases(queryString);
  690. }
  691. /// <summary>
  692. /// Get the names of all persistent classes that implement/extend the given interface/class
  693. /// </summary>
  694. /// <param name="className"></param>
  695. /// <returns></returns>
  696. public string[] GetImplementors(string className)
  697. {
  698. // assumption is that all session factories are configured the same way,
  699. // so it doesn't matter which session factory answers this question
  700. return AnyFactory.GetImplementors(className);
  701. }
  702. /// <summary>
  703. /// Get a class name, using query language imports
  704. /// </summary>
  705. /// <param name="name"></param>
  706. /// <returns></returns>
  707. public string GetImportedClassName(string name)
  708. {
  709. // assumption is that all session factories are configured the same way,
  710. // so it doesn't matter which session factory answers this question
  711. return AnyFactory.GetImportedClassName(name);
  712. }
  713. /// <summary>
  714. /// Get the default query cache
  715. /// </summary>
  716. public IQueryCache QueryCache
  717. {
  718. // assumption is that all session factories are configured the same way,
  719. // so it doesn't matter which session factory answers this question
  720. get { return AnyFactory.QueryCache; }
  721. }
  722. /// <summary>
  723. /// Get a particular named query cache, or the default cache
  724. /// </summary>
  725. /// <param name="regionName">the name of the cache region, or null for the default
  726. /// query cache</param>
  727. /// <returns>the existing cache, or a newly created cache if none by that
  728. /// region name</returns>
  729. public IQueryCache GetQueryCache(string regionName)
  730. {
  731. // assumption is that all session factories are configured the same way,
  732. // so it doesn't matter which session factory answers this question
  733. return AnyFactory.GetQueryCache(regionName);
  734. }
  735. public ResultSetMappingDefinition GetResultSetMapping(string resultSetRef)
  736. {
  737. return AnyFactory.GetResultSetMapping(resultSetRef);
  738. }
  739. public IIdentifierGenerator GetIdentifierGenerator(string rootEntityName)
  740. {
  741. // since all configs are same, we return any
  742. return AnyFactory.GetIdentifierGenerator(rootEntityName);
  743. }
  744. public ITransactionFactory TransactionFactory
  745. {
  746. get { return AnyFactory.TransactionFactory; }
  747. }
  748. public ISQLExceptionConverter SQLExceptionConverter
  749. {
  750. // assumption is that all session factories are configured the same way,
  751. // so it doesn't matter which session factory answers this question
  752. get { return AnyFactory.SQLExceptionConverter; }
  753. }
  754. public SQLFunctionRegistry SQLFunctionRegistry
  755. {
  756. // assumption is that all session factories are configured the same way,
  757. // so it doesn't matter which session factory answers this question
  758. get { return AnyFactory.SQLFunctionRegistry; }
  759. }
  760. public IEntityNotFoundDelegate EntityNotFoundDelegate
  761. {
  762. // assumption is that all session factories are configured the same way,
  763. // so it doesn't matter which session factory answers this question
  764. get { return AnyFactory.EntityNotFoundDelegate; }
  765. }
  766. /// <summary>
  767. /// Gets the ICurrentSessionContext instance attached to this session factory.
  768. /// </summary>
  769. public ICurrentSessionContext CurrentSessionContext
  770. {
  771. get { return AnyFactory.CurrentSessionContext; }
  772. }
  773. /// <summary>
  774. /// Unsupported. This is a technical decision. See <see cref="OpenSession(System.Data.IDbConnection)"/> for an explanation.
  775. /// </summary>
  776. /// <param name="connection"></param>
  777. /// <param name="flushBeforeCompletionEnabled"></param>
  778. /// <param name="autoCloseSessionEnabled"></param>
  779. /// <param name="connectionReleaseMode"></param>
  780. /// <returns></returns>
  781. public ISession OpenSession(IDbConnection connection, bool flushBeforeCompletionEnabled, bool autoCloseSessionEnabled,
  782. ConnectionReleaseMode connectionReleaseMode)
  783. {
  784. throw new NotSupportedException();
  785. }
  786. ISet<string> ISessionFactoryImplementor.GetCollectionRolesByEntityParticipant(string entityName)
  787. {
  788. // assumption is that all session factories are configured the same way,
  789. // so it doesn't matter which session factory answers this question
  790. return AnyFactory.GetCollectionRolesByEntityParticipant(entityName);
  791. }
  792. public IEntityPersister TryGetEntityPersister(string entityName)
  793. {
  794. // assumption is that all session factories are configured the same way,
  795. // so it doesn't matter which session factory answers this question
  796. return AnyFactory.TryGetEntityPersister(entityName);
  797. }
  798. /// <summary> The cache of table update timestamps</summary>
  799. public UpdateTimestampsCache UpdateTimestampsCache
  800. {
  801. // assumption is that all session factories are configured the same way,
  802. // so it doesn't matter which session factory answers this question
  803. get { return AnyFactory.UpdateTimestampsCache; }
  804. }
  805. /// <summary> Get a named second-level cache region</summary>
  806. public ICache GetSecondLevelCacheRegion(string regionName)
  807. {
  808. // assumption is that all session factories are configured the same way,
  809. // so it doesn't matter which session factory answers this question
  810. return AnyFactory.GetSecondLevelCacheRegion(regionName);
  811. }
  812. public NamedQueryDefinition GetNamedQuery(string queryName)
  813. {
  814. // assumption is that all session factories are configured the same way,
  815. // so it doesn't matter which session factory answers this question
  816. return AnyFactory.GetNamedQuery(queryName);
  817. }
  818. public NamedSQLQueryDefinition GetNamedSQLQuery(string queryName)
  819. {
  820. // assumption is that all session factories are configured the same way,
  821. // so it doesn't matter which session factory answers this question
  822. return AnyFactory.GetNamedSQLQuery(queryName);
  823. }
  824. /// <summary> Statistics SPI</summary>
  825. public IStatisticsImplementor StatisticsImplementor
  826. {
  827. // assumption is that all session factories are configured the same way,
  828. // so it doesn't matter which session factory answers this question
  829. get { return AnyFactory.StatisticsImplementor; }
  830. }
  831. public QueryPlanCache QueryPlanCache
  832. {
  833. // assumption is that all session factories are configured the same way,
  834. // so it doesn't matter which session factory answers this question
  835. get { return AnyFactory.QueryPlanCache; }
  836. }
  837. public IType GetIdentifierType(string className)
  838. {
  839. // assumption is that all session factories are configured the same way,
  840. // so it doesn't matter which session factory answers this question
  841. return AnyFactory.GetIdentifierType(className);
  842. }
  843. public string GetIdentifierPropertyName(string className)
  844. {
  845. // assumption is that all session factories are configured the same way,
  846. // so it doesn't matter which session factory answers this question
  847. return AnyFactory.GetIdentifierPropertyName(className);
  848. }
  849. public IType GetReferencedPropertyType(string className, string propertyName)
  850. {
  851. // assumption is that all session factories are configured the same way,
  852. // so it doesn't matter which session factory answers this question
  853. return AnyFactory.GetReferencedPropertyType(className, propertyName);
  854. }
  855. public bool HasNonIdentifierPropertyNamedId(string className)
  856. {
  857. // assumption is that all session factories are configured the same way,
  858. // so it doesn't matter which session factory answers this question
  859. return AnyFactory.HasNonIdentifierPropertyNamedId(className);
  860. }
  861. #endregion
  862. /// <summary>
  863. /// Create a new databinder.
  864. /// </summary>
  865. /// <returns></returns>
  866. public IDatabinder OpenDatabinder()
  867. {
  868. throw new NotImplementedException();
  869. }
  870. /// <summary>
  871. /// Get all <c>ClassMetadata</c> as a <c>IDictionary</c> from <c>Type</c>
  872. /// to metadata object
  873. /// </summary>
  874. /// <returns></returns>
  875. public IDictionary GetAllClassMetadata()
  876. {
  877. //throw new NotImplementedException();
  878. return (IDictionary) this.AnyFactory.GetAllClassMetadata();
  879. }
  880. /// <summary>
  881. /// Get all <c>CollectionMetadata</c> as a <c>IDictionary</c> from role name
  882. /// to metadata object
  883. /// </summary>
  884. /// <returns></returns>
  885. public IDictionary GetAllCollectionMetadata()
  886. {
  887. return (IDictionary) this.AnyFactory.GetAllCollectionMetadata();
  888. }
  889. /// <summary>
  890. /// Get the persister for a class
  891. /// </summary>
  892. public IEntityPersister GetEntityPersister(System.Type clazz)
  893. {
  894. throw new NotImplementedException();
  895. //return AnyFactory.GetEntityPersister(clazz);
  896. }
  897. /// <summary>
  898. /// Get the persister for the named class
  899. /// </summary>
  900. /// <param name="className">The name of the class that is persisted.</param>
  901. /// <param name="throwIfNotFound">Whether to throw an exception if the class is not found,
  902. /// or just return <see langword="null" /></param>
  903. /// <returns>The <see cref="IEntityPersister"/> for the class.</returns>
  904. /// <exception cref="MappingException">If no <see cref="IEntityPersister"/> can be found
  905. /// and throwIfNotFound is true.</exception>
  906. public IEntityPersister GetEntityPersister(string className, bool throwIfNotFound)
  907. {
  908. //return AnyFactory.GetEntityPersister(className, throwIfNotFound);
  909. throw new NotImplementedException();
  910. }
  911. /// <summary>
  912. /// Obtain an ADO.NET connection
  913. /// </summary>
  914. /// <returns></returns>
  915. public IDbConnection OpenConnection()
  916. {
  917. throw new NotSupportedException();
  918. }
  919. /// <summary>
  920. /// Unsupported
  921. /// </summary>
  922. /// <param name="conn"></param>
  923. public void CloseConnection(IDbConnection conn)
  924. {
  925. throw new NotSupportedException();
  926. }
  927. /// <summary>
  928. /// Get the identifier generator for the hierarchy
  929. /// </summary>
  930. public IIdentifierGenerator GetIdentifierGenerator(System.Type rootClass)
  931. {
  932. throw new NotImplementedException();
  933. //return AnyFactory.GetIdentifierGenerator(rootClass);
  934. }
  935. /// <summary>
  936. /// Not supported
  937. /// </summary>
  938. public ISession OpenSession(IDbConnection connection, ConnectionReleaseMode connectionReleaseMode)
  939. {
  940. throw new NotSupportedException();
  941. }
  942. /// <summary>
  943. /// Retrieves a set of all the collection roles in which the given entity
  944. /// is a participant, as either an index or an element.
  945. /// </summary>
  946. /// <param name="entityName">The entity name for which to get the collection roles.</param>
  947. /// <returns>
  948. /// Set of all the collection roles in which the given entityName participates.
  949. /// </returns>
  950. public ISet GetCollectionRolesByEntityParticipant(string entityName)
  951. {
  952. // assumption is that all session factories are configured the same way,
  953. // so it doesn't matter which session factory answers this question
  954. return (ISet) this.AnyFactory.GetCollectionRolesByEntityParticipant(entityName);
  955. }
  956. public IDictionary GetAllSecondLevelCacheRegions()
  957. {
  958. // assumption is that all session factories are configured the same way,
  959. // so it doesn't matter which session factory answers this question
  960. return (IDictionary) this.AnyFactory.GetAllSecondLevelCacheRegions();
  961. }
  962. public IQueryTranslator[] GetQuery(string queryString, bool shallow, IDictionary<string, IFilter> enabledFilters)
  963. {
  964. throw new NotImplementedException();
  965. }
  966. }
  967. }