PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/src/FluentNHibernate/Mapping/ClassMap.cs

https://github.com/signoredems/fluent-nhibernate
C# | 465 lines | 301 code | 96 blank | 68 comment | 16 complexity | 849c73ece04200a11394df4dbda951de MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6. using FluentNHibernate.Mapping.Providers;
  7. using FluentNHibernate.MappingModel;
  8. using FluentNHibernate.MappingModel.ClassBased;
  9. using FluentNHibernate.Utils;
  10. using NHibernate.Persister.Entity;
  11. namespace FluentNHibernate.Mapping
  12. {
  13. public class ClassMap<T> : ClasslikeMapBase<T>, IMappingProvider
  14. {
  15. protected readonly AttributeStore<ClassMapping> attributes = new AttributeStore<ClassMapping>();
  16. private readonly IList<JoinMapping> joins = new List<JoinMapping>();
  17. private readonly OptimisticLockBuilder<ClassMap<T>> optimisticLock;
  18. /// <summary>
  19. /// Specify caching for this entity.
  20. /// </summary>
  21. public CachePart Cache { get; private set; }
  22. protected IIdentityMappingProvider id;
  23. private readonly IList<ImportPart> imports = new List<ImportPart>();
  24. private bool nextBool = true;
  25. protected DiscriminatorPart discriminator;
  26. protected IVersionMappingProvider version;
  27. protected ICompositeIdMappingProvider compositeId;
  28. private readonly HibernateMappingPart hibernateMappingPart = new HibernateMappingPart();
  29. private readonly PolymorphismBuilder<ClassMap<T>> polymorphism;
  30. private SchemaActionBuilder<ClassMap<T>> schemaAction;
  31. protected TuplizerMapping tuplizerMapping;
  32. public ClassMap()
  33. {
  34. optimisticLock = new OptimisticLockBuilder<ClassMap<T>>(this, value => attributes.Set(x => x.OptimisticLock, value));
  35. polymorphism = new PolymorphismBuilder<ClassMap<T>>(this, value => attributes.Set(x => x.Polymorphism, value));
  36. schemaAction = new SchemaActionBuilder<ClassMap<T>>(this, value => attributes.Set(x => x.SchemaAction, value));
  37. Cache = new CachePart(typeof(T));
  38. }
  39. ClassMapping IMappingProvider.GetClassMapping()
  40. {
  41. var mapping = new ClassMapping(attributes.CloneInner());
  42. mapping.Type = typeof(T);
  43. mapping.Name = typeof(T).AssemblyQualifiedName;
  44. foreach (var property in properties)
  45. mapping.AddProperty(property.GetPropertyMapping());
  46. foreach (var component in components)
  47. mapping.AddComponent(component.GetComponentMapping());
  48. if (version != null)
  49. mapping.Version = version.GetVersionMapping();
  50. foreach (var oneToOne in oneToOnes)
  51. mapping.AddOneToOne(oneToOne.GetOneToOneMapping());
  52. foreach (var collection in collections)
  53. mapping.AddCollection(collection.GetCollectionMapping());
  54. foreach (var reference in references)
  55. mapping.AddReference(reference.GetManyToOneMapping());
  56. foreach (var any in anys)
  57. mapping.AddAny(any.GetAnyMapping());
  58. foreach (var subclass in subclasses.Values)
  59. mapping.AddSubclass(subclass.GetSubclassMapping());
  60. foreach (var join in joins)
  61. mapping.AddJoin(join);
  62. if (discriminator != null)
  63. mapping.Discriminator = ((IDiscriminatorMappingProvider)discriminator).GetDiscriminatorMapping();
  64. if (Cache.IsDirty)
  65. mapping.Cache = ((ICacheMappingProvider)Cache).GetCacheMapping();
  66. if (id != null)
  67. mapping.Id = id.GetIdentityMapping();
  68. if (compositeId != null)
  69. mapping.Id = compositeId.GetCompositeIdMapping();
  70. if (!mapping.IsSpecified("TableName"))
  71. mapping.SetDefaultValue(x => x.TableName, GetDefaultTableName());
  72. foreach (var filter in filters)
  73. mapping.AddFilter(filter.GetFilterMapping());
  74. foreach (var storedProcedure in storedProcedures)
  75. mapping.AddStoredProcedure(storedProcedure.GetStoredProcedureMapping());
  76. mapping.Tuplizer = tuplizerMapping;
  77. return mapping;
  78. }
  79. private string GetDefaultTableName()
  80. {
  81. var tableName = EntityType.Name;
  82. if (EntityType.IsGenericType)
  83. {
  84. // special case for generics: GenericType_GenericParameterType
  85. tableName = EntityType.Name.Substring(0, EntityType.Name.IndexOf('`'));
  86. foreach (var argument in EntityType.GetGenericArguments())
  87. {
  88. tableName += "_";
  89. tableName += argument.Name;
  90. }
  91. }
  92. return "`" + tableName + "`";
  93. }
  94. public HibernateMapping GetHibernateMapping()
  95. {
  96. var hibernateMapping = ((IHibernateMappingProvider)hibernateMappingPart).GetHibernateMapping();
  97. foreach (var import in imports)
  98. hibernateMapping.AddImport(import.GetImportMapping());
  99. return hibernateMapping;
  100. }
  101. IEnumerable<string> IMappingProvider.GetIgnoredProperties()
  102. {
  103. return new string[0];
  104. }
  105. public HibernateMappingPart HibernateMapping
  106. {
  107. get { return hibernateMappingPart; }
  108. }
  109. public virtual CompositeIdentityPart<T> CompositeId()
  110. {
  111. var part = new CompositeIdentityPart<T>();
  112. compositeId = part;
  113. return part;
  114. }
  115. public virtual CompositeIdentityPart<TId> CompositeId<TId>(Expression<Func<T, TId>> expression)
  116. {
  117. var part = new CompositeIdentityPart<TId>(ReflectionHelper.GetProperty(expression).Name);
  118. compositeId = part;
  119. return part;
  120. }
  121. public VersionPart Version(Expression<Func<T, object>> expression)
  122. {
  123. return Version(ReflectionHelper.GetProperty(expression).ToMember());
  124. }
  125. protected virtual VersionPart Version(Member property)
  126. {
  127. var versionPart = new VersionPart(typeof(T), property);
  128. version = versionPart;
  129. return versionPart;
  130. }
  131. public virtual DiscriminatorPart DiscriminateSubClassesOnColumn<TDiscriminator>(string columnName, TDiscriminator baseClassDiscriminator)
  132. {
  133. var part = new DiscriminatorPart(columnName, typeof(T), subclasses.Add, new TypeReference(typeof(TDiscriminator)));
  134. discriminator = part;
  135. attributes.Set(x => x.DiscriminatorValue, baseClassDiscriminator);
  136. return part;
  137. }
  138. public virtual DiscriminatorPart DiscriminateSubClassesOnColumn<TDiscriminator>(string columnName)
  139. {
  140. var part = new DiscriminatorPart(columnName, typeof(T), subclasses.Add, new TypeReference(typeof(TDiscriminator)));
  141. discriminator = part;
  142. return part;
  143. }
  144. public virtual DiscriminatorPart DiscriminateSubClassesOnColumn(string columnName)
  145. {
  146. return DiscriminateSubClassesOnColumn<string>(columnName);
  147. }
  148. public virtual IdentityPart Id(Expression<Func<T, object>> expression)
  149. {
  150. return Id(expression, null);
  151. }
  152. public virtual IdentityPart Id(Expression<Func<T, object>> expression, string column)
  153. {
  154. Member property = ReflectionHelper.GetProperty(expression).ToMember();
  155. var part = column == null ? new IdentityPart(EntityType, property) : new IdentityPart(EntityType, property);
  156. if (column != null)
  157. part.Column(column);
  158. id = part;
  159. return part;
  160. }
  161. public virtual IdentityPart Id<TColumn>(string column)
  162. {
  163. var part = new IdentityPart(typeof(T), typeof(TColumn), column);
  164. if (column != null)
  165. part.Column(column);
  166. id = part;
  167. return part;
  168. }
  169. [Obsolete("Inline definitions of subclasses are depreciated. Please create a derived class from SubclassMap in the same way you do with ClassMap.")]
  170. public virtual void JoinedSubClass<TSubclass>(string keyColumn, Action<JoinedSubClassPart<TSubclass>> action) where TSubclass : T
  171. {
  172. var subclass = new JoinedSubClassPart<TSubclass>(keyColumn);
  173. action(subclass);
  174. subclasses[typeof(TSubclass)] = subclass;
  175. }
  176. /// <summary>
  177. /// Sets the hibernate-mapping schema for this class.
  178. /// </summary>
  179. /// <param name="schema">Schema name</param>
  180. public void Schema(string schema)
  181. {
  182. attributes.Set(x => x.Schema, schema);
  183. }
  184. /// <summary>
  185. /// Sets the table for the class.
  186. /// </summary>
  187. /// <param name="tableName">Table name</param>
  188. public void Table(string tableName)
  189. {
  190. attributes.Set(x => x.TableName, tableName);
  191. }
  192. /// <summary>
  193. /// Inverse next boolean
  194. /// </summary>
  195. [DebuggerBrowsable(DebuggerBrowsableState.Never)]
  196. public ClassMap<T> Not
  197. {
  198. get
  199. {
  200. nextBool = !nextBool;
  201. return this;
  202. }
  203. }
  204. /// <summary>
  205. /// Sets this entity to be lazy-loaded (overrides the default lazy load configuration).
  206. /// </summary>
  207. public void LazyLoad()
  208. {
  209. attributes.Set(x => x.Lazy, nextBool);
  210. nextBool = true;
  211. }
  212. /// <summary>
  213. /// Sets additional tables for the class via the NH 2.0 Join element.
  214. /// </summary>
  215. /// <param name="tableName">Joined table name</param>
  216. /// <param name="action">Joined table mapping</param>
  217. public void Join(string tableName, Action<JoinPart<T>> action)
  218. {
  219. var join = new JoinPart<T>(tableName);
  220. action(join);
  221. joins.Add(((IJoinMappingProvider)join).GetJoinMapping());
  222. }
  223. /// <summary>
  224. /// Imports an existing type for use in the mapping.
  225. /// </summary>
  226. /// <typeparam name="TImport">Type to import.</typeparam>
  227. public ImportPart ImportType<TImport>()
  228. {
  229. var part = new ImportPart(typeof(TImport));
  230. imports.Add(part);
  231. return part;
  232. }
  233. /// <summary>
  234. /// Set the mutability of this class, sets the mutable attribute.
  235. /// </summary>
  236. public void ReadOnly()
  237. {
  238. attributes.Set(x => x.Mutable, !nextBool);
  239. nextBool = true;
  240. }
  241. /// <summary>
  242. /// Sets this entity to be dynamic update
  243. /// </summary>
  244. public void DynamicUpdate()
  245. {
  246. attributes.Set(x => x.DynamicUpdate, nextBool);
  247. nextBool = true;
  248. }
  249. /// <summary>
  250. /// Sets this entity to be dynamic insert
  251. /// </summary>
  252. public void DynamicInsert()
  253. {
  254. attributes.Set(x => x.DynamicInsert, nextBool);
  255. nextBool = true;
  256. }
  257. public ClassMap<T> BatchSize(int size)
  258. {
  259. attributes.Set(x => x.BatchSize, size);
  260. return this;
  261. }
  262. /// <summary>
  263. /// Sets the optimistic locking strategy
  264. /// </summary>
  265. public OptimisticLockBuilder<ClassMap<T>> OptimisticLock
  266. {
  267. get { return optimisticLock; }
  268. }
  269. public PolymorphismBuilder<ClassMap<T>> Polymorphism
  270. {
  271. get { return polymorphism; }
  272. }
  273. public SchemaActionBuilder<ClassMap<T>> SchemaAction
  274. {
  275. get { return schemaAction; }
  276. }
  277. public void CheckConstraint(string constraint)
  278. {
  279. attributes.Set(x => x.Check, constraint);
  280. }
  281. public void Persister<TPersister>() where TPersister : IEntityPersister
  282. {
  283. Persister(typeof(TPersister));
  284. }
  285. private void Persister(Type type)
  286. {
  287. Persister(type.AssemblyQualifiedName);
  288. }
  289. private void Persister(string type)
  290. {
  291. attributes.Set(x => x.Persister, type);
  292. }
  293. public void Proxy<TProxy>()
  294. {
  295. Proxy(typeof(TProxy));
  296. }
  297. public void Proxy(Type type)
  298. {
  299. Proxy(type.AssemblyQualifiedName);
  300. }
  301. public void Proxy(string type)
  302. {
  303. attributes.Set(x => x.Proxy, type);
  304. }
  305. public void SelectBeforeUpdate()
  306. {
  307. attributes.Set(x => x.SelectBeforeUpdate, nextBool);
  308. nextBool = true;
  309. }
  310. /// <summary>
  311. /// Defines a SQL 'where' clause used when retrieving objects of this type.
  312. /// </summary>
  313. public void Where(string where)
  314. {
  315. attributes.Set(x => x.Where, where);
  316. }
  317. /// <summary>
  318. /// Sets the SQL statement used in subselect fetching.
  319. /// </summary>
  320. /// <param name="subselectSql">Subselect SQL Query</param>
  321. public void Subselect(string subselectSql)
  322. {
  323. attributes.Set(x => x.Subselect, subselectSql);
  324. }
  325. /// <summary>
  326. /// Specifies an entity-name.
  327. /// </summary>
  328. /// <remarks>See http://nhforge.org/blogs/nhibernate/archive/2008/10/21/entity-name-in-action-a-strongly-typed-entity.aspx</remarks>
  329. public void EntityName(string entityName)
  330. {
  331. attributes.Set(x => x.EntityName, entityName);
  332. }
  333. /// <overloads>
  334. /// Applies a named filter to this one-to-many.
  335. /// </overloads>
  336. /// <summary>
  337. /// Applies a named filter to this one-to-many.
  338. /// </summary>
  339. /// <param name="condition">The condition to apply</param>
  340. /// <typeparam name="TFilter">
  341. /// The type of a <see cref="FilterDefinition"/> implementation
  342. /// defining the filter to apply.
  343. /// </typeparam>
  344. public ClassMap<T> ApplyFilter<TFilter>(string condition) where TFilter : FilterDefinition, new()
  345. {
  346. var part = new FilterPart(new TFilter().Name, condition);
  347. filters.Add(part);
  348. return this;
  349. }
  350. /// <summary>
  351. /// Applies a named filter to this one-to-many.
  352. /// </summary>
  353. /// <typeparam name="TFilter">
  354. /// The type of a <see cref="FilterDefinition"/> implementation
  355. /// defining the filter to apply.
  356. /// </typeparam>
  357. public ClassMap<T> ApplyFilter<TFilter>() where TFilter : FilterDefinition, new()
  358. {
  359. return ApplyFilter<TFilter>(null);
  360. }
  361. public ClassMap<T> Tuplizer(TuplizerMode mode, Type tuplizerType)
  362. {
  363. tuplizerMapping = new TuplizerMapping();
  364. tuplizerMapping.Mode = mode;
  365. tuplizerMapping.Type = new TypeReference(tuplizerType);
  366. return this;
  367. }
  368. }
  369. }