首先這裏發一下結構圖,由於是重寫的,可是代碼都是同樣全部以下:web
這裏我先說一下看了大部分的DDD文章都是採用的WCF作服務,這裏呢我用的是webapi作服務,WCF和WEBAPI的區別能夠去百度下。sql
好了。如今咱們看下automapper的具體實現。數據庫
由於automapper又一個Profile類,而咱們本身寫的類去繼承這個類,全部以下圖:api
上圖是建立映射關係,下面就去添加映射跨域
這些作完了 咱們如今須要使用app
這裏的dto類型是CostomDTO 也就是數據傳輸對象。cors
下面咱們來看下工做單元,下面我直接貼代碼框架
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; } } }
這是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; } }
這是IUnitOfWorkContext接口代碼async
由於我是基於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; } } }
完成這裏接下來就是工做單元的實現類
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 } }
如今呢就是個人倉儲,由於是聚合根的緣故,因此聚合後的根有本身特有的倉儲代碼以下。
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(); } } }
而後是個人總倉儲的實現
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(); } } }
如今回到咱們的服務層
系統初始化我採用的是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(); } } }
下面貼上測試結果,WEB端請求的是webapi其中涉及到跨域請求問題,採用的是微軟的cors包。
須要代碼的同窗點這裏。
PS:採用了autofac IOC框架 automapper 映射框架 Log4Net 日誌 ORM是EF 用的是codefirst 運行的時候只須要改web.config的數據庫鏈接就能夠了。
連接: 百度 密碼: 3baw