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

      

  • 相关阅读:
    postgresql 常用命令
    CF235D Graph Game
    win10 uwp 获得Slider拖动结束的值
    win10 uwp 获得Slider拖动结束的值
    win10 uwp 如何打包Nuget给其他人
    win10 uwp 如何打包Nuget给其他人
    C#判断文件是否被混淆
    C#判断文件是否被混淆
    win10 uwp 使用动画修改 Grid column 的宽度
    win10 uwp 使用动画修改 Grid column 的宽度
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/7357244.html
Copyright © 2020-2023  润新知