/// <summary> /// Start the service and bind all of the sub-services /// </summary> public bool Start() { // notify startup this.Starting?.Invoke(this, EventArgs.Empty); if (this.m_running) { return(true); } // Verify schema version using (ModelDataContext mdc = new ModelDataContext(this.m_configuration.ReadonlyConnectionString)) { Version dbVer = new Version(mdc.fn_OpenIzSchemaVersion()), oizVer = typeof(SqlServerPersistenceService).Assembly.GetName().Version; if (oizVer < dbVer) { throw new InvalidOperationException(String.Format("Invalid Schema Version. OpenIZ version {0} is older than the database schema version {1}", oizVer, dbVer)); } this.m_tracer.TraceInformation("OpenIZ Schema Version {0}", dbVer); } // Iterate the persistence services foreach (var t in typeof(SqlServerPersistenceService).GetTypeInfo().Assembly.ExportedTypes.Where(o => o.Namespace == "OpenIZ.Persistence.Data.MSSQL.Services.Persistence" && !o.GetTypeInfo().IsAbstract)) { try { this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Loading {0}...", t.AssemblyQualifiedName); ApplicationContext.Current.AddServiceProvider(t); } catch (Exception e) { this.m_tracer.TraceEvent(TraceEventType.Error, e.HResult, "Error adding service {0} : {1}", t.AssemblyQualifiedName, e); } } // Now iterate through the map file and ensure we have all the mappings, if a class does not exist create it try { this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Creating secondary model maps..."); var map = ModelMap.Load(typeof(SqlServerPersistenceService).GetTypeInfo().Assembly.GetManifestResourceStream("OpenIZ.Persistence.Data.MSSQL.Data.ModelMap.xml")); foreach (var itm in map.Class) { // Is there a persistence service? var idpType = typeof(IDataPersistenceService <>); Type modelClassType = Type.GetType(itm.ModelClass), domainClassType = Type.GetType(itm.DomainClass); idpType = idpType.MakeGenericType(modelClassType); if (modelClassType.IsAbstract || domainClassType.IsAbstract) { continue; } // Already created if (ApplicationContext.Current.GetService(idpType) != null) { continue; } this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Creating map {0} > {1}", modelClassType, domainClassType); if (modelClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IBaseEntityData)) && domainClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IDbBaseData))) { // Construct a type var pclass = typeof(GenericBasePersistenceService <,>); pclass = pclass.MakeGenericType(modelClassType, domainClassType); ApplicationContext.Current.AddServiceProvider(pclass); } else if (modelClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IIdentifiedEntity)) && domainClassType.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IDbIdentified))) { // Construct a type var pclass = typeof(GenericIdentityPersistenceService <,>); pclass = pclass.MakeGenericType(modelClassType, domainClassType); ApplicationContext.Current.AddServiceProvider(pclass); } } } catch (Exception e) { this.m_tracer.TraceEvent(TraceEventType.Error, e.HResult, "Error initializing local persistence: {0}", e); throw e; } // Bind some basic service stuff ApplicationContext.Current.GetService <IDataPersistenceService <Core.Model.Security.SecurityUser> >().Inserting += (o, e) => { if (String.IsNullOrEmpty(e.Data.SecurityHash)) { e.Data.SecurityHash = Guid.NewGuid().ToString(); } }; ApplicationContext.Current.GetService <IDataPersistenceService <Core.Model.Security.SecurityUser> >().Updating += (o, e) => { e.Data.SecurityHash = Guid.NewGuid().ToString(); }; // Attempt to cache concepts this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Caching concept dictionary..."); if (ApplicationContext.Current.GetService <IDataCachingService>() != null) { new Thread((o) => { int t; ApplicationContext.Current.GetService <IDataPersistenceService <Core.Model.DataTypes.Concept> >().Query(c => c.Key == c.Key, 0, 10000, null, out t); ApplicationContext.Current.GetService <IDataPersistenceService <Core.Model.DataTypes.ConceptSet> >().Query(c => c.Key == c.Key, 0, 1000, null, out t); }).Start(); } this.m_running = true; this.Started?.Invoke(this, EventArgs.Empty); return(true); }