abp ddd mysql_基于ABP VNext及CodeFirst,迈开走向DDD的第一步

前言:DDD的基础知识这里就不讲了,网上有很多,无外乎 架构从以外的三层变成四层,有聚合、实体、值对象、领域服务等这些概念,我也是最近看了很多,但无从下手,正好我们现有的项目是基于ABP

框架的,虽说也支持DDD,也是分为了4个项目,有领域有Domain,但感觉还是个三层项目,想了想,最大的问题还是收到新的任务后,总是从数据库开始,然后T4生成实体,没有太多的去进行领域划分。所以本次

我们使用EFCore的CodeFirst和ABPVnext来体验一下怎么在项目中真正的运用DDD。

--------------------------------------------------------------------------------------------------------------------------------------------------

新建项目

68756e0d2a7b6ea546534026b5863e16.png

我这里使用ABP的CLI命令创建的,当然也可以直接在网站(https://www.abp.io/get-started)上下载

切换后,我们使用下面这俩命令创建一下数据库

Add-Migration "Init"Update-DataBase

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

重点来了

接下来我们正式从一个订单的领域开始, 首先看一张图

3b27d506935c1460f25a2572c5fc2ddf.png

首先我们先创建个地址的值对象

///

///地址(值对象)///

public classAddress : ValueObject

{public String Street { get; private set; }public String City { get; private set; }public String State { get; private set; }public String Country { get; private set; }public String ZipCode { get; private set; }publicAddress() { }public Address(string street, string city, string state, string country, stringzipcode)

{

Street=street;

City=city;

State=state;

Country=country;

ZipCode=zipcode;

}protected override IEnumerableGetAtomicValues()

{//Using a yield return statement to return each element one at a time

yield returnStreet;yield returnCity;yield returnState;yield returnCountry;yield returnZipCode;

}

}

创建实体

///

///订单明细实体///

public classOrderItem : Entity

{public virtual Guid OrderId { get; protected set; }public virtual Guid ProductId { get; protected set; }public virtual int Count { get; protected set; }protectedOrderItem()

{

}internal OrderItem(Guid orderId, Guid productId, intcount)

{

OrderId=orderId;

ProductId=productId;

Count=count;

}internal void ChangeCount(intnewCount)

{

Count=newCount;

}public override object[] GetKeys()

{return newObject[] { OrderId, ProductId };

}

}

创建订单聚合根

///

///订单聚合根///

public class Order : AggregateRoot{public virtual string ReferenceNo { get; protected set; }public virtual int TotalItemCount { get; protected set; }public virtual DateTime CreationTime { get; protected set; }public virtual List OrderLines { get; protected set; }public Address Address { get; protected set; }//值对象

public string UserName { get; protected set; }protectedOrder()

{

}public Order(Guid id, string referenceNo, stringuserName, Address address)

{

Check.NotNull(referenceNo, nameof(referenceNo));

Id=id;

ReferenceNo=referenceNo;

Address=address;

OrderLines= new List();

CreationTime=DateTime.Now;

UserName=userName;

}public void AddProduct(Guid productId, intcount)

{if (count <= 0)

{throw newArgumentException("You can not add zero or negative count of products!",

nameof(count)

);

}var existingLine = OrderLines.FirstOrDefault(ol => ol.ProductId ==productId);if (existingLine == null)

{

OrderLines.Add(new OrderItem(this.Id, productId, count));

}else{

existingLine.ChangeCount(existingLine.Count+count);

}

TotalItemCount+=count;

}

}

然后在Context中添加

public DbSet Orders { get; set; }public DbSet OrderItems { get; set; }

public static void ConfigureDDDTest(thisModelBuilder builder)

{

Check.NotNull(builder, nameof(builder));/*Configure your own tables/entities inside here*/

//builder.Entity(b =>//{//b.ToTable(DDDTestConsts.DbTablePrefix + "YourEntities", DDDTestConsts.DbSchema);// //...//});

builder.Entity(b =>{

b.ToTable(DDDTestConsts.DbTablePrefix+ "Orders", DDDTestConsts.DbSchema);

b.ConfigureByConvention();

b.OwnsOne(o=> o.Address, a =>{

a.WithOwner();

});//b.Property(x => x.Name).IsRequired().HasMaxLength(128);

});

builder.Entity(b =>{

b.ToTable(DDDTestConsts.DbTablePrefix+ "OrderLines", DDDTestConsts.DbSchema);

b.ConfigureByConvention();

b.HasKey(x=> new{ x.OrderId, x.ProductId });//b.Property(x => x.Name).IsRequired().HasMaxLength(128);

});

}

此时我们再执行迁移命令,会发现数据库中多了俩张表,值对象在聚合中

0b824a70e9b0fa3ac5e42aa1d74211dd.png

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

这时候我们执行个创建的方法是,会出现这个错误

cb0930ebca4ca255ca53a86b940ea50c.png

这个时候只需要把 base.OnModelCreating(builder);,移到builder.ConfigureDDDTest();下面即可

a56538c2b755adfeb934de4583fec3a2.png

自定义仓储的话,我们需要把接口定义在领域层,把实现放在基础设施层

public class OrderRepository : EfCoreRepository, IOrderRepository

{public OrderRepository(IDbContextProviderdbContextProvider)

:base(dbContextProvider)

{

}public async TaskGet(Guid orderId)

{var order = awaitDbContext

.Orders

.Include(x=>x.Address)

.FirstOrDefaultAsync(o=> o.Id ==orderId);if (order == null)

{

order=DbContext

.Orders

.Local

.FirstOrDefault(o=> o.Id ==orderId);

}if (order != null)

{awaitDbContext.Entry(order)

.Collection(i=>i.OrderLines).LoadAsync();

}returnorder;

}

}

58c9caa4c183cea8f3f7df734436b0b0.png

整体实现下来,不知道有没有点对DDD的感觉呢?

参考:

https://www.cnblogs.com/richieyang/p/5373250.html

https://cn.abp.io/blog/Abp/Abp-vNext-Announcement

https://docs.abp.io/en/abp/latest/

https://github.com/abpframework/abp/issues/2640

https://docs.microsoft.com/zh-cn/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/microservice-domain-model

https://github.com/dotnet-architecture/eShopOnContainers

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值