PageRenderTime 60ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Data.Linq/src/DbLinq/Data/Linq/Sugar/Implementation/DataMapper.cs

https://github.com/ekovalenko-softheme/mono
C# | 214 lines | 131 code | 21 blank | 62 comment | 26 complexity | fc9f09bc774d6d3b7ac79a9bf97bdf22 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Unlicense
  1. #region MIT license
  2. //
  3. // MIT license
  4. //
  5. // Copyright (c) 2007-2008 Jiri Moudry, Pascal Craponne
  6. //
  7. // Permission is hereby granted, free of charge, to any person obtaining a copy
  8. // of this software and associated documentation files (the "Software"), to deal
  9. // in the Software without restriction, including without limitation the rights
  10. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. // copies of the Software, and to permit persons to whom the Software is
  12. // furnished to do so, subject to the following conditions:
  13. //
  14. // The above copyright notice and this permission notice shall be included in
  15. // all copies or substantial portions of the Software.
  16. //
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. // THE SOFTWARE.
  24. //
  25. #endregion
  26. using System;
  27. using System.Collections.Generic;
  28. using System.Collections.ObjectModel;
  29. using System.Data.Linq.Mapping;
  30. using System.Linq;
  31. using System.Reflection;
  32. using DbLinq.Data.Linq.Sugar.Expressions;
  33. #if MONO_STRICT
  34. using System.Data.Linq;
  35. #else
  36. using DbLinq.Data.Linq;
  37. #endif
  38. namespace DbLinq.Data.Linq.Sugar.Implementation
  39. {
  40. internal class DataMapper : IDataMapper
  41. {
  42. /// <summary>
  43. /// Returns a table given a type, or null if the type is not mapped
  44. /// </summary>
  45. /// <param name="tableType"></param>
  46. /// <param name="dataContext"></param>
  47. /// <returns></returns>
  48. public virtual string GetTableName(Type tableType, DataContext dataContext)
  49. {
  50. var tableDescription = dataContext.Mapping.GetTable(tableType);
  51. if (tableDescription != null)
  52. return tableDescription.TableName;
  53. return null;
  54. }
  55. public virtual string GetColumnName(TableExpression tableExpression, MemberInfo memberInfo, DataContext dataContext)
  56. {
  57. return GetColumnName(tableExpression.Type, memberInfo, dataContext);
  58. }
  59. public virtual string GetColumnName(Type tableType, MemberInfo memberInfo, DataContext dataContext)
  60. {
  61. var tableDescription = dataContext.Mapping.GetTable(tableType);
  62. var columnDescription = tableDescription.RowType.GetDataMember(memberInfo);
  63. if (columnDescription != null)
  64. return columnDescription.MappedName;
  65. return null;
  66. }
  67. public virtual IList<MemberInfo> GetPrimaryKeys(TableExpression tableExpression, DataContext dataContext)
  68. {
  69. var tableDescription = dataContext.Mapping.GetTable(tableExpression.Type);
  70. if (tableDescription != null)
  71. return GetPrimaryKeys(tableDescription);
  72. return null;
  73. }
  74. public virtual IList<MemberInfo> GetPrimaryKeys(MetaTable tableDescription)
  75. {
  76. return (from column in tableDescription.RowType.IdentityMembers select column.Member).ToList();
  77. }
  78. /// <summary>
  79. /// Lists table mapped columns
  80. /// </summary>
  81. /// <param name="tableDescription"></param>
  82. /// <returns></returns>
  83. public IList<MemberInfo> GetColumns(MetaTable tableDescription)
  84. {
  85. return (from column in tableDescription.RowType.PersistentDataMembers select column.Member).ToList();
  86. }
  87. /// <summary>
  88. /// Returns association definition, if any
  89. /// </summary>
  90. /// <param name="thisTableExpression">The table referenced by the assocation (the type holding the member)</param>
  91. /// <param name="memberInfo">The memberInfo related to association</param>
  92. /// <param name="otherType"></param>
  93. /// <param name="otherKey">The keys in the associated table</param>
  94. /// <param name="joinType"></param>
  95. /// <param name="joinID"></param>
  96. /// <param name="dataContext"></param>
  97. /// <returns>ThisKey</returns>
  98. public virtual IList<MemberInfo> GetAssociation(TableExpression thisTableExpression, MemberInfo memberInfo, Type otherType, out IList<MemberInfo> otherKey, out TableJoinType joinType, out string joinID, DataContext dataContext)
  99. {
  100. var thisTableDescription = dataContext.Mapping.GetTable(thisTableExpression.Type);
  101. var thisAssociation =
  102. (from association in thisTableDescription.RowType.Associations
  103. where association.ThisMember.Member == memberInfo
  104. select association).SingleOrDefault();
  105. if (thisAssociation != null)
  106. {
  107. // by default, join is inner
  108. joinType = TableJoinType.Inner;
  109. joinID = thisAssociation.ThisMember.MappedName;
  110. if (string.IsNullOrEmpty(joinID))
  111. throw Error.BadArgument("S0108: Association name is required to ensure join uniqueness");
  112. var otherTableDescription = dataContext.Mapping.GetTable(otherType);
  113. bool thisKeyHasNullables, otherKeyHasNullables;
  114. var thisKey = GetAssociationKeys(thisTableDescription, thisAssociation.ThisKey, dataContext,
  115. out thisKeyHasNullables);
  116. otherKey = GetAssociationKeys(otherTableDescription, thisAssociation.OtherKey, dataContext,
  117. out otherKeyHasNullables);
  118. // we just test here the left join (since associations are symmetric,
  119. // we can only find left joins here, and the otherKeyHasNullables is
  120. // always equal to thisKeyHasNullables)
  121. if (thisKeyHasNullables)
  122. joinType |= TableJoinType.LeftOuter;
  123. return thisKey;
  124. }
  125. otherKey = null;
  126. joinType = TableJoinType.Default;
  127. joinID = null;
  128. return null;
  129. }
  130. /// <summary>
  131. /// Enumerates Keys for a given table.
  132. /// Keys can be provided as input. If none provided, PKs are taken from table
  133. /// </summary>
  134. /// <param name="description"></param>
  135. /// <param name="keys">Keys to be used, leave empty to use PKs instead</param>
  136. /// <param name="dataContext"></param>
  137. /// <param name="hasNullableKeys">returned as true if some keys can be null (we then have an outer join)</param>
  138. /// <returns></returns>
  139. protected virtual IList<MemberInfo> GetAssociationKeys(MetaTable description, ReadOnlyCollection<MetaDataMember> keys,
  140. DataContext dataContext, out bool hasNullableKeys)
  141. {
  142. var sourceKeys = keys;
  143. if (sourceKeys.Count == 0)
  144. sourceKeys = description.RowType.IdentityMembers;
  145. hasNullableKeys = false;
  146. var members = new List<MemberInfo>();
  147. foreach (var sourceKey in sourceKeys)
  148. {
  149. members.Add(sourceKey.Member);
  150. if (sourceKey.CanBeNull)
  151. hasNullableKeys = true;
  152. }
  153. return members;
  154. }
  155. public IList<MemberInfo> GetEntitySetAssociations(Type type)
  156. {
  157. // BUG: This is ignoring External Mappings from XmlMappingSource.
  158. // TODO: Should be cached in a static thread safe cache.
  159. return type.GetProperties()
  160. .Where(p => p.PropertyType.IsGenericType
  161. && (p.PropertyType.GetGenericTypeDefinition() == typeof(System.Data.Linq.EntitySet<>)
  162. #if !MONO_STRICT
  163. || p.PropertyType.GetGenericTypeDefinition() == typeof(DbLinq.Data.Linq.EntitySet<>)
  164. #endif
  165. )
  166. && p.IsDefined(typeof(AssociationAttribute), true))
  167. .Cast<MemberInfo>().ToList();
  168. }
  169. public IList<MemberInfo> GetEntityRefAssociations(Type type)
  170. {
  171. // BUG: This is ignoring External Mappings from XmlMappingSource.
  172. // TODO: Should be cached in a static thread safe cache.
  173. List<MemberInfo> associations = new List<MemberInfo>();
  174. foreach (var p in type.GetProperties())
  175. {
  176. AssociationAttribute associationAttribute = p.GetCustomAttributes(typeof(AssociationAttribute), true).FirstOrDefault() as AssociationAttribute;
  177. if (associationAttribute != null)
  178. {
  179. FieldInfo field = type.GetField(associationAttribute.Storage, BindingFlags.NonPublic | BindingFlags.Instance);
  180. if (field != null && field.FieldType.IsGenericType &&
  181. #if MONO_STRICT
  182. field.FieldType.GetGenericTypeDefinition() == typeof(System.Data.Linq.EntityRef<>)
  183. #else
  184. field.FieldType.GetGenericTypeDefinition() == typeof(DbLinq.Data.Linq.EntityRef<>)
  185. #endif
  186. )
  187. associations.Add(p);
  188. }
  189. }
  190. return associations;
  191. }
  192. }
  193. }