PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/wojilu/ORM/MappingClass.cs

https://bitbucket.org/kingshine/wojilu
C# | 386 lines | 233 code | 97 blank | 56 comment | 41 complexity | d964fcaca658f4b3af558456d4f0f912 MD5 | raw file
Possible License(s): MIT
  1. /*
  2. * Copyright 2010 www.wojilu.com
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. using System;
  17. using System.Collections;
  18. using System.Collections.Generic;
  19. using System.Reflection;
  20. using wojilu.Data;
  21. using wojilu.DI;
  22. using wojilu.Reflection;
  23. using System.Web;
  24. using System.IO;
  25. using System.Web.Hosting;
  26. namespace wojilu.ORM {
  27. /// <summary>
  28. /// 实体类和数据表关联映射的信息
  29. /// </summary>
  30. [Serializable]
  31. public class MappingClass {
  32. private static readonly ILog logger = LogManager.GetLogger( typeof( MappingClass ) );
  33. private IDictionary _assemblyList = new Hashtable();
  34. private IDictionary _classList = new Hashtable();
  35. private IDictionary _typeList = new Hashtable();
  36. private IDictionary _factoryList;
  37. private List<IInterceptor> _interceptorList = new List<IInterceptor>();
  38. private List<String> _tableList = new List<String>();
  39. /// <summary>
  40. /// ORM需要加载的所有程序集
  41. /// </summary>
  42. public IDictionary AssemblyList {
  43. get { return _assemblyList; }
  44. set { _assemblyList = value; }
  45. }
  46. /// <summary>
  47. /// 所有需要持久化的实体的 EntityInfo(每个EntityInfo包括类型、映射的表名等信息)
  48. /// </summary>
  49. public IDictionary ClassList {
  50. get { return _classList; }
  51. set { _classList = value; }
  52. }
  53. /// <summary>
  54. /// 所有需要持久化的实体的类型(type)
  55. /// </summary>
  56. public IDictionary TypeList {
  57. get { return _typeList; }
  58. set { _typeList = value; }
  59. }
  60. /// <summary>
  61. /// 所有需要持久化的实体的创建工厂
  62. /// </summary>
  63. public IDictionary FactoryList {
  64. get { return _factoryList; }
  65. set { _factoryList = value; }
  66. }
  67. /// <summary>
  68. /// 所有拦截器
  69. /// </summary>
  70. public List<IInterceptor> InterceptorList {
  71. get { return _interceptorList; }
  72. set { _interceptorList = value; }
  73. }
  74. /// <summary>
  75. /// 所有表名
  76. /// </summary>
  77. public List<String> TableList {
  78. get { return _tableList; }
  79. set { _tableList = value; }
  80. }
  81. private MappingClass() {
  82. }
  83. private static volatile MappingClass _instance;
  84. private static Object _syncRoot = new object();
  85. public static MappingClass Instance {
  86. get {
  87. if (_instance == null) {
  88. lock (_syncRoot) {
  89. if (_instance == null) _instance = loadInstance();
  90. }
  91. }
  92. return _instance;
  93. }
  94. }
  95. public static void Clear() {
  96. _instance = null;
  97. }
  98. private static MappingClass loadInstance() {
  99. logger.Info( "begin MappingClass ..." );
  100. MappingClass result;
  101. if (strUtil.HasText( DbConfig.Instance.MetaDLL )) {
  102. result = loadByCacheDLL();
  103. }
  104. else {
  105. result = loadByReflection();
  106. }
  107. logger.Info( "end MappingClass ..." );
  108. return result;
  109. }
  110. private static MappingClass loadByCacheDLL() {
  111. String dllPath = DbConfig.Instance.GetMetaDllAbsPath();
  112. MappingClass map = null;
  113. try {
  114. map = EasyDB.LoadFromFile( dllPath ) as MappingClass;
  115. }
  116. catch (Exception exception) {
  117. logger.Error( "[MappingClass.loadInstance=>db.LoadFromFile( DbConfig.Instance.MetaDLL=" + DbConfig.Instance.MetaDLL + ")]:" + exception.Message );
  118. }
  119. if (map == null) {
  120. map = loadByReflection();
  121. EasyDB.SaveToFile( map, dllPath );
  122. }
  123. else
  124. logger.Info( "load meta from cache" );
  125. checkMultiDB( map );
  126. return map;
  127. }
  128. public static MappingClass loadByReflection() {
  129. logger.Info( "loadByReflection" );
  130. IList asmList = DbConfig.Instance.AssemblyList;
  131. MappingClass map = new MappingClass();
  132. for (int i = 0; i < asmList.Count; i++) {
  133. Assembly assembly = ObjectContext.LoadAssembly( asmList[i].ToString() );
  134. map.AssemblyList[asmList[i].ToString()] = assembly;
  135. Type[] typeArray = ObjectContext.FindTypes( asmList[i].ToString() );
  136. foreach (Type type in typeArray) {
  137. ResolveOneType( map, type );
  138. }
  139. logger.Info( "loaded assembly: " + assembly.FullName );
  140. }
  141. logger.Info( "FinishPropertyInfo" );
  142. FinishPropertyInfo( map.ClassList );
  143. logger.Info( "cacheInterceptor" );
  144. cacheInterceptor( map );
  145. logger.Info( "AccessorUtil.Init" );
  146. MetaList list = new MetaList( map.AssemblyList, map.ClassList );
  147. map.FactoryList = AccessorUtil.Init( list );
  148. checkMultiDB( map );
  149. return map;
  150. }
  151. //------------------------------------------------------------------------------
  152. private static void ResolveOneType( MappingClass map, Type t ) {
  153. map.TypeList.Add( t.FullName, t );
  154. //if (!t.IsAbstract && ( t.IsSubclassOf( typeof( ObjectBase ) ) || t is IEntity )) {
  155. // map.ClassList[t.FullName] = EntityInfo.GetByType( t );
  156. // logger.Info( "Loading Type : " + t.FullName );
  157. //}
  158. // 1029
  159. logger.Info( "Loading Type : " + t.FullName );
  160. if (rft.IsInterface( t, typeof( IEntity ) ) && !OrmHelper.IsEntityBase( t )) {
  161. map.ClassList.Add( t.FullName, EntityInfo.GetByType( t ) );
  162. }
  163. }
  164. private static IDictionary FinishPropertyInfo( IDictionary mapClassList ) {
  165. foreach (DictionaryEntry entry in mapClassList) {
  166. EntityInfo info = entry.Value as EntityInfo;
  167. foreach (EntityPropertyInfo ep in info.SavedPropertyList) {
  168. //if (mapClassList.Contains( ep.Type.FullName )) {
  169. // ep.EntityInfo = mapClassList[ep.Type.FullName] as EntityInfo;
  170. //}
  171. if (mapClassList.Contains( ep.Type.FullName ) && ep.SaveToDB) {
  172. ep.EntityInfo = mapClassList[ep.Type.FullName] as EntityInfo;
  173. ep.IsEntity = true;
  174. info.EntityPropertyList.Add( ep );
  175. }
  176. ep.ColumnName = getColumnName( ep.Property, mapClassList );
  177. //if (!(!ep.SaveToDB || ep.IsList)) {
  178. // info.ColumnList = info.ColumnList + ep.ColumnName + ",";
  179. //}
  180. if (isSavedProperty( ep )) info.ColumnList = info.ColumnList + ep.ColumnName + ",";
  181. }
  182. foreach (EntityPropertyInfo ep in info.PropertyListAll) {
  183. info.AddPropertyToHashtable( ep );
  184. }
  185. info.ColumnList = info.ColumnList.Trim().TrimEnd( new char[] { ',' } );
  186. //if (!((info.Type.BaseType == typeof( ObjectBase )) || info.Type.BaseType.IsAbstract)) {
  187. // EntityInfo info4 = mapClassList[info.Type.BaseType.FullName] as EntityInfo;
  188. // info4.ChildEntityList.Add( info );
  189. //}
  190. // 找到父对象,然后给父对象的ChildEntityList加上当前对象
  191. if (updateParentInfo( info )) {
  192. EntityInfo parentEi = mapClassList[info.Type.BaseType.FullName] as EntityInfo;
  193. parentEi.ChildEntityList.Add( info );
  194. }
  195. }
  196. return mapClassList;
  197. }
  198. //1029
  199. private static Boolean updateParentInfo( EntityInfo info ) {
  200. if (info.Type.BaseType == typeof( Object )) return false;
  201. if (OrmHelper.IsEntityBase( info.Type.BaseType )) return false;
  202. if (info.Type.BaseType.IsAbstract) return false;
  203. return true;
  204. }
  205. //1029
  206. private static Boolean isSavedProperty( EntityPropertyInfo ep ) {
  207. if (ep.SaveToDB) return true;
  208. return false;
  209. }
  210. private static void cacheInterceptor( MappingClass map ) {
  211. List<object> interceptor = DbConfig.Instance.Interceptor;
  212. for (int i = 0; i < interceptor.Count; i++) {
  213. Dictionary<String, object> info = interceptor[i] as Dictionary<String, object>;
  214. String asmName = info["AssemblyName"].ToString();
  215. String typeName = info["TypeFullName"].ToString();
  216. IInterceptor obj = rft.GetInstance( asmName, typeName ) as IInterceptor;
  217. if (obj == null) {
  218. throw new Exception( "load ORM interceptor error( Assembly:" + asmName + ", Type:" + typeName + ")" );
  219. }
  220. map.InterceptorList.Add( obj );
  221. }
  222. }
  223. private static void checkMultiDB( MappingClass map ) {
  224. if (DbConfig.Instance.IsCheckDatabase == false) {
  225. logger.Info( "skip check database" );
  226. return;
  227. }
  228. if (map.TableList == null) map.TableList = new List<String>();
  229. if (DbConfig.Instance.ConnectionStringTable == null || DbConfig.Instance.ConnectionStringTable.Count == 0) {
  230. createDB( map );
  231. return;
  232. }
  233. logger.Info( "begin check database..." );
  234. foreach (KeyValuePair<String, ConnectionString> kv in DbConfig.Instance.GetConnectionStringMap()) {
  235. String connectionString = kv.Value.StringContent;
  236. if (strUtil.IsNullOrEmpty( connectionString ))
  237. throw new NotImplementedException( lang.get( "exConnectionString" ) + ":" + kv.Key );
  238. DatabaseType dbtype = kv.Value.DbType;
  239. IDatabaseChecker databaseChecker = DataFactory.GetDatabaseChecker( dbtype );
  240. databaseChecker.ConnectionString = connectionString;
  241. databaseChecker.DatabaseType = dbtype;
  242. logger.Info( "CheckDatabase" );
  243. databaseChecker.CheckDatabase();
  244. logger.Info( "CheckTable" );
  245. databaseChecker.CheckTable( map, kv.Key );
  246. logger.Info( "GetTables" );
  247. map.TableList.AddRange( databaseChecker.GetTables() );
  248. }
  249. logger.Info( "end check database..." );
  250. }
  251. private static void createDB( MappingClass map ) {
  252. logger.Info( "begin create database ..." );
  253. DatabaseType dbtype = DatabaseType.Access;
  254. IDatabaseChecker databaseChecker = DataFactory.GetDatabaseChecker( dbtype );
  255. databaseChecker.DatabaseType = dbtype;
  256. logger.Info( "CheckDatabase" );
  257. databaseChecker.CheckDatabase();
  258. logger.Info( "CheckTable" );
  259. databaseChecker.CheckTable( map, DbConfig.DefaultDbName );
  260. logger.Info( "GetTables" );
  261. map.TableList = databaseChecker.GetTables();
  262. }
  263. private static String getColumnName( PropertyInfo property, IDictionary mapClassList ) {
  264. ColumnAttribute attribute = ReflectionUtil.GetAttribute( property, typeof( ColumnAttribute ) ) as ColumnAttribute;
  265. if ((attribute != null) && strUtil.HasText( attribute.Name )) {
  266. return attribute.Name;
  267. }
  268. if (mapClassList.Contains( property.PropertyType.FullName )) {
  269. return (property.Name + "Id");
  270. }
  271. if (property.PropertyType.IsInterface) {
  272. return String.Format( "{0}Id", property.PropertyType.Name.TrimStart( new char[] { 'I' } ) );
  273. }
  274. if (property.PropertyType.Name == "IList") {
  275. throw new Exception( "property data type can not be IList" );
  276. }
  277. return property.Name;
  278. }
  279. //-------------------------------------------------------------------------------------------------------
  280. internal Boolean ContainsTable( String tableName ) {
  281. for (int i = 0; i < TableList.Count; i++) {
  282. if (strUtil.EqualsIgnoreCase( TableList[i], tableName )) {
  283. return true;
  284. }
  285. }
  286. return false;
  287. }
  288. }
  289. }