基于Mvc3,Ef,领域驱动电子商务系统的EShop开发
最近做了2个小型的电子商务系统,最近的一个是自己带的项目,由于功能比较简单,业务关系又不是很复杂,所以想依靠了解许久但不觉深入的“领域驱动”思想自己,做一个开发的架构,完成之后希望在这里做一个记录:
今天只是个概述,希望以后有机会细致的展开。
1.大家都比较喜欢直接看层次图:
Domain.Entity存在上层领域比较关心领域实体,其中包含着自己的相应业务逻辑;
Domain.Respository中包含系统的数据持久处理,Interface提供相应的仓储接口及所有仓储类需要集成的公共仓储BaseRespository,其中包含都需要的基本的增删改查操作,对应的仓储接口则提供领域所关心的数据持久方法;
我这里仓储使用的是EF以及传统的Ado;
Service层主要提供了不太好归于各个领域实体本身的操作,在服务层进行相应的组合,如订单的提交,需要涉及到,诸如购物车商品状态的修改,商品虚拟库存的修改,用户身份等级及积分使用等,需要建立相应的OrderService进行组合封装,并且订单状态的改变,所带来相应领域实体的“状态回滚”。以及对于我等草根码农来说,快速修改代码及新功能新要求的满足,能够更好的找到单一修改代码的地方还是很方便的因为他就在OrderService中;
Web层使用的是MVC3,在上层来说相对于以前使用Mvc最大的特点就是知道尽量在Controller中写少的业务逻辑,不然我们又会回到以前WebForm时代点击一个Button后面有无数的逻辑及状态需要维护;web层中的Model更多的放了一些诸如第三方的API,以及实现的SSO,Cookie,Session的处理以页面所需要的ViewModel;
2.直接上代码(都是不全的代表了意思)
Domain.Respository
namespace EShop.Domain { public interface IRespository<T> where T:class{ IQueryable<T> All(); T Create(T t); int Delete(T t); int Update(T t); } public class BaseResipository<T>:IRespository<T> where T:class { protected readonly DbContext Context; public BaseRepository(DbContext context) { Context = context; } public IQueryable<T> All() { return Context.Set<T>().AsQueryable(); } public virtual T Create(T TObject) { var newEntry = Context.Set<T>().Add(TObject); Context.SaveChanges(); return newEntry; } public virtual int Delete(T TObject) { Context.Set<T>().Remove(TObject); return Context.SaveChanges(); } public virtual int Update(T TObject) { var entry = Context.Entry(TObject); Context.Set<T>().Attach(TObject); entry.State = EntityState.Modified; return Context.SaveChanges(); } }
实现仓储:
namespace EShop.Domain { public interface ItemRespository : IRespository<ItemEntity> { IEnumerable<dynamic> GetAllItems(); } }
ItemRespository的实现:
namespace EShop.Domain.Respository.RespsitoryContext { public class ItemEFRespository : BaseResipository<ItemEntity>, ItemRespository { private readonly ItemContext _context; public ItemEFRespository(ItemContext context) : base(context) { _context = context; } public IEnumerable<dynamic> GetAllItems() { return _context.Items; } } }
#region Cart /// <summary> /// 获取购物车明细里商品规格信息,根据商品sku编号 /// </summary> /// <param name="ItemSkuId">商品sku编号</param> /// <returns></returns> public static string GetItemGgValue(int ItemSkuId) { string s = ""; var queryResult = from i in _dp.mdc.SKU_Attribute_Value where i.SKU_Id == ItemSkuId select i; foreach(SKU_Attribute_Value sav in queryResult) { s += string.Format("{0}:{1};",sav.Attribute_Name,sav.Value_Name); } s = s.EndsWith(";") ? s.Substring(s.Length - 1) : s; return s; } public static int AddCart(newShopCar cart) { _dp.mdc.newShopCar.InsertOnSubmit(cart); _dp.mdc.SubmitChanges(); return cart.CartID; } public static int AddCartItem(newShopCartItem cartItem) { _dp.mdc.newShopCartItem.InsertOnSubmit(cartItem); _dp.mdc.SubmitChanges(); return cartItem.CartItemID; } #endregion
Domain.Entity:
namespace EShop.Domain { public class ItemEntity { #region 实体 public int Itemid { get; set; } public string ItemName { get; set; } public float ItemPrice { get; set; } public int ItemCount { get; set; } #endregion ItemRespository _respository; public ItemEntity(ItemRespository Respository) { _respository = Respository; } #region 行为 /// <summary> /// 获取指定商品 /// </summary> /// <param name="itemID"></param> /// <returns></returns> public ItemEntity GetModel(int itemID) { return _respository.GetModel(itemID); } #endregion } }
Web层:
Controller:
public class CartController : Controller { // // GET: /Cart/ /// <summary> /// 商品添加至购物车 /// </summary> /// <param name="id">itemID_count</param> /// <returns></returns> public ActionResult Index(string id) { //防Sql注入 SqlChecker SqlChecker = new SqlChecker(this.Request, this.Response, Framework.Globals.SqlCheckRedirectUrl); SqlChecker.Check(); //由Cookie中读取登录用户ID int _customerId = Framework.SSO.GetUid(); int _itemID = 0; int _itemCount = 0; try { _itemID = int.Parse(id.Split('-')[0]); _itemCount = int.Parse(id.Split('-')[1]); } catch { return Content(string.Format("<Script language='javascript'>alert('{0}');history.go(-1);</Script>", "参数错误,非法访问URL!")); } try { ItemEntity item = new ItemEntity(); item = item.GetModel(_itemID); ShopCartEntity shopCart = new ShopCartEntity(); shopCart.AddItemToShopCart(_customerId, item); ShopCartViewModel v = new ShopCartViewModel(); v.UserID = _customerId; v.ShopCartItem = shopCart.GetUserShopCart(_customerId); return View(v); } catch { return Content(string.Format("<Script language='javascript'>alert('{0}');history.go(-1);</Script>", "添加失败!")); } } } }
ViewModel:
public class ShopCartViewModel { public int UserID { get; set; } public List<ShopCartEntity> ShopCartItem { get; set; } public int ItemCount { get; set; } public float SumPrice { get; set; } }
/// <summary> /// 首页 /// </summary> /// <returns></returns> public ActionResult Index() { SqlChecker SqlChecker = new SqlChecker(this.Request, this.Response, Framework.Globals.SqlCheckRedirectUrl); SqlChecker.Check(); HomeIndexViewModel v = new HomeIndexViewModel(); v.HotProducts = ProductRules.GetHotProducts(5, "今日热销"); v.RecommendProducts = ProductRules.GetHotProducts(5, "热点推荐"); v.SecKillProducts = ProductRules.GetHotProducts(10, "秒杀专区"); v.ZhiDeMai = ProductRules.GetHotProducts(10, "值得买"); v.FeaturedProducts = ProductRules.GetFeaturedProducts(3); //精选区 int userid = SSO.GetUid(); return View(v); }
由于项目时间比较短,所以有一些代码是直接用的以前的,掺杂在一起有时会显得比较混乱,也是第一次尝试“领域驱动”的开发,分享在这里,希望园子里的同学不管是架构方向的,领域驱动方向的,Mvc方向的针对于现有的层次提出宝贵意见,建议。小弟不剩感激。话说国足6:1新加坡,美国要对叙利亚动武了,生活再继续...