PageRenderTime 58ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/src/FluentNHibernate/Mapping/ClassMap.cs

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