EF、Repository、Factory、Service间关系

EF和Repository

  • 实体(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来实现对数据库的操作

  

原文地址:https://www.cnblogs.com/panpanwelcome/p/7357244.html