DDD領域驅動之干貨(三)完結篇!


首先這里發一下結構圖,因為是重寫的,但是代碼都是一樣所有如下:

這里我先說一下看了大部分的DDD文章都是采用的WCF做服務,這里呢我用的是webapi做服務,WCF和WEBAPI的區別可以去百度下。

好了。現在我們看下automapper的具體實現。

因為automapper又一個Profile類,而我們自己寫的類去繼承這個類,所有如下圖:

上圖是創建映射關系,下面就去添加映射

這些做完了 我們現在需要使用

這里的dto類型是CostomDTO 也就是數據傳輸對象。

下面我們來看下工作單元,下面我直接貼代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.Repository.UnitOfWork
{
    /// <summary>
    /// 表示所有集成該接口都是工作單元的一種實現
    /// </summary>
    public interface IUnitOfWork
    {
        /// <summary>
        /// 提交
        /// </summary>
        void Commit();

        /// <summary>
        /// 異步提交
        /// </summary>
        /// <returns></returns>
        Task CommitSyncAsync();

        /// <summary>
        /// 回滾
        /// </summary>
        void Rollback();

        /// <summary>
        /// 已經提交過了
        /// </summary>
        bool Committed { get; }

        /// <summary>
        /// 事務支持
        /// </summary>
        //bool DistributedTransactionSupported { get; }
    }
}
View Code

這是IUnitOfWork接口代碼。

using KuRuMi.Mio.DoMainModel.BaseModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.Repository.UnitOfWork
{
    public interface IUnitOfWorkContext : IUnitOfWork, IDisposable
    {
        /// <summary>
        /// 將指定的聚合根標注為“新建”狀態。
        /// </summary>
        /// <typeparam name="TAggregateRoot">需要標注狀態的聚合根類型。</typeparam>
        /// <param name="obj">需要標注狀態的聚合根。</param>
        void RegisterNew<TAggregateRoot>(TAggregateRoot obj)
            where TAggregateRoot : class, IAggregateRoot;
        /// <summary>
        /// 將指定的聚合根標注為“更改”狀態。
        /// </summary>
        /// <typeparam name="TAggregateRoot">需要標注狀態的聚合根類型。</typeparam>
        /// <param name="obj">需要標注狀態的聚合根。</param>
        void RegisterModified<TAggregateRoot>(TAggregateRoot obj)
            where TAggregateRoot : class, IAggregateRoot;
        /// <summary>
        /// 將指定的聚合根標注為“刪除”狀態。
        /// </summary>
        /// <typeparam name="TAggregateRoot">需要標注狀態的聚合根類型。</typeparam>
        /// <param name="obj">需要標注狀態的聚合根。</param>
        void RegisterDeleted<TAggregateRoot>(TAggregateRoot obj)
            where TAggregateRoot : class, IAggregateRoot;
    }
}
View Code

這是IUnitOfWorkContext接口代碼

因為我是基於EF實現的所以這里多了一層EF的工作單元代碼

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.Repository.UnitOfWork
{
    /// <summary>
    /// 表示是EF倉儲的一種實現
    /// </summary>
    public interface IEFUnitOfWorkContext : IUnitOfWorkContext
    {
        DbContext Context { get; }
    }
}
View Code

完成這里接下來就是工作單元的實現類

using KuRuMi.Mio.DoMainModel.BaseModel;
using KuRuMi.Mio.DoMain.Infrastructure;
using KuRuMi.Mio.DoMain.Repository.EFRepository;
using KuRuMi.Mio.DoMain.Repository.UnitOfWork;
using System.Data.Entity;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.Repository.BaseUnitOfWork
{
    public class UnitOfWorkContext: DisposableObject, IEFUnitOfWorkContext
    {
        private KurumiMioDbContext kurumi = null;

        public UnitOfWorkContext() {
            kurumi = new KurumiMioDbContext();
        }

        public DbContext Context { get { return kurumi; } }

        #region 工作單元
        public bool Committed { get; protected set; }

        /// <summary>
        /// 同步提交
        /// </summary>
        public void Commit()
        {
            if (!Committed)
            {
                //kurumi.Value.GetValidationErrors();
                Context.SaveChanges();
                Committed = true;
            }
        }

        /// <summary>
        /// 異步提交
        /// </summary>
        /// <returns></returns>
        public async Task CommitSyncAsync()
        {
            if (!Committed)
            {
                await Context.SaveChangesAsync();
                Committed = true;
            }
        }
        /// <summary>
        /// 釋放資源
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!Committed)
                    Commit();
                Context.Dispose();
                kurumi.Dispose();
            }
        }

        /// <summary>
        /// 回滾
        /// </summary>
        public void Rollback()
        {
            Committed = false;
        }
        #endregion

        #region IEFUnitOfWorkContext接口
        /// <summary>
        /// 刪除未提交
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="obj"></param>
        public void RegisterDeleted<TAggregateRoot>(TAggregateRoot obj) where TAggregateRoot : class, IAggregateRoot
        {
            Context.Entry(obj).State = EntityState.Deleted;
            Committed = false;
        }

        /// <summary>
        /// 修改未提交
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="obj"></param>
        public void RegisterModified<TAggregateRoot>(TAggregateRoot obj) where TAggregateRoot : class, IAggregateRoot
        {
            if (Context.Entry(obj).State == EntityState.Detached)
            {
                Context.Set<TAggregateRoot>().Attach(obj);
            }
            Context.Entry(obj).State = EntityState.Modified;
            Committed = false;
        }

        /// <summary>
        /// 新建未提交
        /// </summary>
        /// <typeparam name="TAggregateRoot"></typeparam>
        /// <param name="obj"></param>
        public void RegisterNew<TAggregateRoot>(TAggregateRoot obj) where TAggregateRoot : class, IAggregateRoot
        {
            var state = Context.Entry(obj).State;
            if (state == EntityState.Detached)
            {
                Context.Entry(obj).State = EntityState.Added;
            }
            Committed = false;
        }
        #endregion
    }
}
View Code

現在呢就是我的倉儲,因為是聚合根的緣故,所以聚合后的根有自己特有的倉儲代碼如下。

using KuRuMi.Mio.DoMainModel.Model;
using KuRuMi.Mio.DoMainModel.Repositories;
using KuRuMi.Mio.DoMain.Repository.EFRepository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.Repository.ModelRepository
{
    public class CostomRepositoryImpl :RepositoryImpl<Costom>, ICostomRepository
    {
        public KurumiMioDbContext context => lazy.Context as KurumiMioDbContext;
        public Costom GetAll()
        {
            string sql = "select * from Costom";
            return context.costom.SqlQuery(sql).FirstOrDefault();
        }
    }
}
View Code

然后是我的總倉儲的實現

using KuRuMi.Mio.DoMainModel.BaseModel;
using KuRuMi.Mio.DoMainModel.Repositories;
using KuRuMi.Mio.DoMain.Repository.BaseUnitOfWork;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace KuRuMi.Mio.DoMain.Repository.EFRepository
{
    /// <summary>
    /// 倉儲的泛型實現
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class RepositoryImpl<TEntity> : IRepository<TEntity> where TEntity : AggregateRoot
    {
        public readonly UnitOfWorkContext lazy = null;
        public RepositoryImpl()
        {
            lazy = new UnitOfWorkContext();

        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="aggregateRoot"></param>
        public virtual void Add(TEntity aggregateRoot)
        {
            lazy.RegisterNew<TEntity>(aggregateRoot);
            lazy.Commit();
        }
        /// <summary>
        /// 通過key獲取聚合根
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual TEntity GetKey(Guid key)
        {
            return lazy.Context.Set<TEntity>().Find(key);
        }

        public virtual IQueryable<TEntity> LoadAll(Expression<Func<TEntity, bool>> predicate)
        {
            return lazy.Context.Set<TEntity>().Where(predicate).AsQueryable();
        }
        /// <summary>
        /// 復雜查詢
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual IQueryable<TEntity> LoadForSql(string sql)
        {
            return lazy.Context.Set<TEntity>().SqlQuery(sql).AsQueryable();
        }

        public virtual IEnumerable<TEntity> LoadListAll(Expression<Func<TEntity, bool>> predicate)
        {
            return lazy.Context.Set<TEntity>().Where(predicate).ToList();
        }
        /// <summary>
        /// 復雜查詢
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual IEnumerable<TEntity> LoadListForSql(string sql)
        {
            return lazy.Context.Set<TEntity>().SqlQuery(sql).ToList();
        }

        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="aggregateRoot"></param>
        public virtual void Remove(TEntity aggregateRoot)
        {
            lazy.RegisterDeleted<TEntity>(aggregateRoot);
            lazy.Commit();
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="aggregateRoot"></param>
        public virtual void Update(TEntity aggregateRoot)
        {
            lazy.RegisterModified<TEntity>(aggregateRoot);
            lazy.Commit();
        }
    }
}
View Code

現在回到我們的服務層

系統初始化我采用的是autofac,至於為什么不采用unity,博主個人喜歡用autofac原因輕量,簡單。

好了下面獻上我的初始化系統類。

using KuRuMi.Mio.DataObject.AutoMapperDTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using KuRuMi.Mio.DoMain.Infrastructure.IocManager;
using KuRuMi.Mio.DoMainModel.Repositories;
using Autofac;

namespace KuRuMi.Mio.BootStarp
{

    /// <summary>
    /// 系統初始化
    /// </summary>
    public class OptionBootStarp
    {
        protected IEnumerable<Assembly> assembles { get; }
        protected IIocManager ioc { get; }
        public OptionBootStarp(IEnumerable<Assembly> ass)
        {
            assembles = ass;
            ioc = IocManager.Instance;
        }
        protected IEnumerable<Type> Repository => assembles.SelectMany(a => a.ExportedTypes.Where(t => t.GetInterfaces().Contains(typeof(IBaseRepository))));
        protected IEnumerable<Type> BaseDTO => assembles.SelectMany(a => a.ExportedTypes.Where(t => t.GetInterfaces().Contains(typeof(IAutoMapper))));

        protected IEnumerable<Type> Services => assembles.SelectMany(a => a.ExportedTypes.Where(t => t.GetInterfaces().Contains(typeof(IService))));
        /// <summary>
        /// 預加載
        /// </summary>
        public void Initialize()
        {
            //加載所有DTO
            BaseDTO.ToList().ForEach(s=> {
                var dtpye= Activator.CreateInstance(s) as IAutoMapper;
                ioc.build.RegisterInstance(dtpye).As<MapperConfigurationImpl>().SingleInstance().PropertiesAutowired();
            });
            //加載所有的倉儲
            Repository.ToList().ForEach(s => {
                if (s.IsClass == true && s.IsGenericType == false)
                {
                    var dtpye = Activator.CreateInstance(s);
                    ioc.build.RegisterType(dtpye.GetType()).As(dtpye.GetType());
                }
            });
            //加載所有服務
            Services.ToList().ForEach(s =>
            {
                if (s.IsClass == true)
                {
                    var stype = Activator.CreateInstance(s);
                    ioc.build.RegisterType(stype.GetType()).As(stype.GetType());
                }
            });
            PostInit();
        }
        /// <summary>
        /// 注入
        /// </summary>
        protected void PostInit() {
            ioc.CompleteBuild();
        }
    }

}
View Code

下面貼上測試結果,WEB端請求的是webapi其中涉及到跨域請求問題,采用的是微軟的cors包。

需要代碼的同學點這里。

PS:采用了autofac IOC框架 automapper 映射框架 Log4Net 日志 ORM是EF 用的是codefirst 運行的時候只需要改web.config的數據庫連接就可以了。

鏈接: 百度 密碼: 3baw


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM