在ABP框架中定义实体(Entity)、值对象(Value Object)和聚合根(Aggregate Root)需要遵循领域驱动设计(DDD)的原则,同时利用ABP提供的基类和接口。以下是具体实现方法:
实体是具有唯一标识且生命周期中状态会发生变化的对象。在ABP中,实体通常继承自Entity
基类或其派生类。
using Volo.Abp.Domain.Entities;
public class Product : Entity // 指定主键类型为Guid
{
public string Name { get; set; }
public decimal Price { get; set; }
public bool IsActive { get; set; }
// 构造函数
public Product(Guid id, string name, decimal price)
{
Id = id;
Name = name;
Price = price;
IsActive = true;
}
// 领域方法:封装业务逻辑
public void ChangePrice(decimal newPrice)
{
if (newPrice <= 0)
throw new BusinessException("价格必须大于0");
Price = newPrice;
}
}
继承FullAuditedEntity
可自动记录创建、修改、删除的用户和时间:
using Volo.Abp.Domain.Entities.Auditing;
public class Order : FullAuditedEntity
{
public Guid CustomerId { get; set; }
public DateTime OrderDate { get; set; }
public OrderStatus Status { get; set; }
public List Items { get; set; }
}
值对象是描述领域中的某个概念但没有唯一标识的对象,通常通过属性值来判断相等性。
[ComplexType]
特性using Volo.Abp.Domain.Entities;
[ComplexType] // EF Core映射为复杂类型
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
// 重写相等性比较
public override bool Equals(object obj)
{
if (obj is not Address other)
return false;
return Street == other.Street &&
City == other.City &&
State == other.State &&
ZipCode == other.ZipCode &&
Country == other.Country;
}
public override int GetHashCode()
{
return HashCode.Combine(Street, City, State, ZipCode, Country);
}
}
public class Customer : Entity
{
public string Name { get; set; }
public Address HomeAddress { get; set; } // 嵌入值对象
}
聚合根是一种特殊的实体,作为聚合的根节点,负责维护聚合内的业务规则和数据一致性。
AggregateRoot
基类using Volo.Abp.Domain.Entities;
public class Order : AggregateRoot
{
public Guid CustomerId { get; private set; }
public DateTime OrderDate { get; private set; }
public OrderStatus Status { get; private set; }
public List Items { get; private set; } = new List();
// 私有构造函数:通过工厂方法创建
private Order() { }
// 工厂方法
public static Order Create(Guid customerId)
{
return new Order
{
Id = Guid.NewGuid(),
CustomerId = customerId,
OrderDate = DateTime.Now,
Status = OrderStatus.Pending
};
}
// 聚合根管理子实体
public void AddItem(Guid productId, int quantity, decimal price)
{
if (quantity <= 0)
throw new BusinessException("商品数量必须大于0");
// 检查是否已存在相同商品
var existingItem = Items.FirstOrDefault(i => i.ProductId == productId);
if (existingItem != null)
{
existingItem.IncreaseQuantity(quantity);
}
else
{
// 创建子实体并添加到聚合
var newItem = OrderItem.Create(Id, productId, quantity, price);
Items.Add(newItem);
}
}
// 领域事件触发
public void Confirm()
{
if (Status != OrderStatus.Pending)
throw new BusinessException("只有待确认的订单可以确认");
Status = OrderStatus.Confirmed;
// 发布领域事件
AddDistributedEvent(new OrderConfirmedEto
{
OrderId = Id,
CustomerId = CustomerId
});
}
}
// 聚合内的子实体
public class OrderItem : Entity
{
public Guid OrderId { get; private set; }
public Guid ProductId { get; private set; }
public string ProductName { get; private set; }
public int Quantity { get; private set; }
public decimal Price { get; private set; }
// 私有构造函数
private OrderItem() { }
// 工厂方法
public static OrderItem Create(Guid orderId, Guid productId, int quantity, decimal price)
{
return new OrderItem
{
Id = Guid.NewGuid(),
OrderId = orderId,
ProductId = productId,
Quantity = quantity,
Price = price
};
}
// 子实体的业务方法
public void IncreaseQuantity(int additionalQuantity)
{
Quantity += additionalQuantity;
}
}
using Volo.Abp.Domain.Repositories;
public interface IOrderRepository : IRepository
{
Task GetWithItemsAsync(Guid id);
}
聚合边界:
不变性约束:
工厂模式:
Order.Create()
)创建聚合根,隐藏复杂的初始化逻辑。领域事件:
AddDomainEvent()
或AddDistributedEvent()
发布事件,处理跨聚合的业务逻辑。在DbContext
中配置实体与数据库表的映射关系:
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
public class MyDbContext : AbpDbContext
{
public DbSet Products { get; set; }
public DbSet Orders { get; set; }
public DbSet OrderItems { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// 配置Order聚合根
builder.Entity(b =>
{
b.ToTable("Orders");
b.ConfigureByConvention();
// 配置聚合内的子实体
b.HasMany(x => x.Items)
.WithOne()
.HasForeignKey(x => x.OrderId)
.IsRequired();
});
// 配置值对象
builder.Entity(b =>
{
b.OwnsOne(x => x.HomeAddress);
});
}
}
实体设计:
Entity
作为基类,避免直接暴露属性的setter。值对象设计:
Equals()
和GetHashCode()
确保正确的相等性比较。聚合根设计:
通过以上方式,你可以在ABP框架中正确实现DDD的实体、值对象和聚合根,构建出符合领域驱动设计原则的应用系统。