EF、Repository、Factory、Service间关系
- 实体(Entities):具备唯一ID,能够被持久化,具备业务逻辑,对应现实世界业务对象。
- 值对象(Value objects):不具有唯一ID,由对象的属性描述,一般为内存中的临时对象,可以用来传递参数或对实体进行补充描述。
- 工厂(Factories):主要用来创建实体,目前架构实践中一般采用IOC容器来实现工厂的功能。
- 仓库(Repositories):用来管理实体的集合,封装持久化框架。
- 服务(Services):为上层建筑提供可操作的接口,负责对领域对象进行调度和封装,同时可以对外提供各种形式的服务。
1.定义Context:
2.定义Context对应的Factory
通用DatabaseFactory的定义:利用反射生成Factory的实例。
get()方法返回Factory实例与Context的绑定关系。如果Context已经存在,不再重新new一个entity,使用已有entity,用于防止方法嵌套,导致两个entity不同
public class DatabaseFactoryBase<T> : IDatabaseFactory<T> where T:DbContext,IDisposable,new() { private T _dataContext; //protected Boolean _objectDisposed; protected static Func<Boolean> _funcNeedCreateInstance = null; protected static Boolean DefaultFuncChecked = false; protected static void CreateDefaultChecker() { Type tdf = typeof(IDatabaseFactory<T>); var targetAssembly = AppDomain.CurrentDomain.GetAssemblies().Where(e => e.IsDynamic == false && e.GlobalAssemblyCache == false && e.FullName.Contains("NewCRM.Common")).FirstOrDefault(); if (targetAssembly == null) return; var factoryTypeName = "NewCRM.Common.DependencyInjection.IocFactory"; var factoryType = targetAssembly.GetType(factoryTypeName); if (factoryType!=null) { var instanceProp = factoryType.GetProperty("Instance", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); if (instanceProp!=null) { var method = instanceProp.PropertyType.GetMethod("GetRegistration", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); if (method != null) { var returnType = method.ReturnType; var lsPropType = returnType.GetProperty("LifeStyle", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).PropertyType; var peRegistration = Expression.Variable(returnType); var boolType = typeof(Boolean); var peResult = Expression.Variable(boolType); var listFullExpression = new List<Expression>(); var expInitResult = Expression.Assign(peResult, Expression.Constant(false)); listFullExpression.Add(expInitResult); var instance = instanceProp.GetValue(null); var expGetRegistration = Expression.Assign(peRegistration, Expression.Call(Expression.Constant(instance), method,Expression.Constant(tdf))); listFullExpression.Add(expGetRegistration); var checkLifeStyle = Expression.OrElse( Expression.Equal(peRegistration, Expression.Constant(null)), Expression.Equal(Expression.Convert(Expression.Property(peRegistration, "LifeStyle"),typeof(Int32)), Expression.Constant(2)) ); var expAssignResult = Expression.IfThen(checkLifeStyle, Expression.Assign(peResult, Expression.Constant(true))); listFullExpression.Add(expAssignResult); var lbRet = Expression.Label(boolType); listFullExpression.Add( Expression.MakeGoto( GotoExpressionKind.Return, lbRet, peResult, boolType ) ); listFullExpression.Add( Expression.Label(lbRet, Expression.Default(boolType))); var m2 = Expression.Lambda<Func<Boolean>>( Expression.Block(new ParameterExpression[] { peRegistration, peResult }, listFullExpression) ); var m3 = m2.Compile(); _funcNeedCreateInstance = m3; } } } } public DatabaseFactoryBase() { //_objectDisposed = false; } /// <summary> /// Dispose underlying resource /// </summary> public virtual void ReleaseCurrentContext() { try { if (_dataContext != null /*&& !_objectDisposed*/) { System.Diagnostics.Debug.WriteLine(String.Format("Database Factory:Release context {0}", typeof(T).FullName)); //_objectDisposed = true; _dataContext.Dispose(); } } finally { _dataContext = null; } } /// <summary> /// Dispose underlying resource /// </summary> public virtual void Dispose() { ReleaseCurrentContext(); } /// <summary> /// Get the factory instance /// </summary> /// <returns>datacontext instance</returns> public virtual IAutoDisposeDataContext<T> Get() { var needCreateInstance = NeedCreateInsance(); if ((!needCreateInstance || UnitTestHelper.UnitTestMode) && _dataContext != null) return new AutoDisposeDataContext<T>(_dataContext,this); _dataContext = new T(); #if DEBUG System.Diagnostics.Debug.WriteLine(String.Format("Database Factory:Creating context {0}", typeof(T).FullName)); #endif return new AutoDisposeDataContext<T>(_dataContext,this); } public virtual bool NeedCreateInsance() { //Type tdf = typeof(IDatabaseFactory<T>); //var instance = IocFactory.Instance; //var impl = instance.GetRegistration(tdf); //Boolean needCreateInstance = false; ////if the impl is null,it use the default factory //if (impl == null || impl.LifeStyle == IocLifeStyle.Transient) //{ // needCreateInstance = true; //} //return needCreateInstance; if (!DefaultFuncChecked) { CreateDefaultChecker(); DefaultFuncChecked = true; } if (_funcNeedCreateInstance != null) return _funcNeedCreateInstance(); return true; } }
定义Context与Factory的绑定关系
public class AutoDisposeDataContext<T> : IAutoDisposeDataContext<T> where T : DbContext, new() { private T _dataContext; private IDatabaseFactory<T> _databaseFactory; public AutoDisposeDataContext(T dataContext, IDatabaseFactory<T> databaseFactory) { _dataContext = dataContext; _databaseFactory = databaseFactory; } public T Context { get { return _dataContext; } } public void Dispose() { Boolean useActualDb = false; if (Context is DbContext) { var adapter = Context as IObjectContextAdapter; if (adapter != null && adapter.ObjectContext != null) useActualDb = true; } if (_databaseFactory.NeedCreateInsance() && (useActualDb || !UnitTestHelper.UnitTestMode)) { Context.Dispose(); _databaseFactory.ReleaseCurrentContext(); } //Type tdf = typeof(IDatabaseFactory<T>); //var instance = IocFactory.Instance; //var impl = instance.GetRegistration(tdf); ////do not dispose object in unit test mode //if ( (impl==null || impl.LifeStyle == IocLifeStyle.Transient) && !UnitTestHelper.UnitTestMode) //{ // _databaseFactory.Dispose(); //} } }
3.每个context中的表对应的Respository的构造函数中,传入所在Context的Factory。
Context对应的RepositoryBase
公共RepositoryBase基类,以及其对factory的调用
目的:各表的Respository通过Factory实现对Context中对应表的增、删、改、查……基本操作。实现的增、删、改、查……基本操作的抽象
Respository:为Service提供服务,为其提供基本的操作。调用
Service:针对特定的业务逻辑,调用Respository来实现对数据库的操作