Luc*_*nde 5 c# domain-driven-design .net-2.0 entity-framework-core
我有一个项目,我在其中按照 DDD 方法使用 Asp.Net Core 2.0。因此,我拥有拥有实体和值对象的聚合根,这些实体和值对象配置为拥有的类型,这是 EF Core 2.0 中的一项新功能。我添加了一个此类配置的示例以更好地阐明。
领域:
public class Address : ValueObject
{
public Address(string street, int number){
Street = street;
Number = number;
}
public string Street {get; private set;}
public int Number {get; private set;}
}
public class Company : AggregateRoot
{
public Address Address {get; private set;}
// Other properties...
// Value objects are immutables so I'm only able to replace it with a new object.
public void UpdateAddress(string street, int number){
Address = new Address(street, number);
}
// Other methods...
}
Run Code Online (Sandbox Code Playgroud)
EF 核心实体配置:
internal class CompanyEntityTypeConfiguration : IEntityTypeConfiguration<Company>
{
public void Configure(EntityTypeBuilder<Company> builder)
{
builder.HasKey(x => x.Id);
builder.OwnsOne(x => x.Address);
}
}
Run Code Online (Sandbox Code Playgroud)
我正在从数据库中检索一个跟踪实体,当我尝试更新 AggregateRoot 并用一个新的值对象替换一个值对象时,我收到一个异常,提示“另一个相同类型的实体已被跟踪”。地址是被跟踪的实体。
因此,解决方案是检索未跟踪但我不想使用这种方法,因为它会在数据库中进行完整更新。那么,如何从 Entity Framework 2.0 跟踪的实体更新值对象(拥有的实体)?
我在使用 ef core 1.0.0 时找到了一个解决方法。我无法再次找到参考将链接放在这里并将学分归功于作者,但就您而言,解决方法如下:
领域:
public class Address : ValueObject
{
public Address(string street, int number)
{
Street = street;
Number = number;
}
public string Street { get; private set; }
public int Number { get; private set; }
#region Value object workaround
public Address WithStreet(string value) => new Address(value, Number);
public Address WithNumber(int value) => new Address(Street, value);
#endregion
}
public class Company : AggregateRoot
{
#region public public Address Address { get; set; }
[NotMapped]
public Address Address { get; set; }
//In the DbContext this property needs to be mapped with a column in a database
private string Address_Street
{
get { return Address.Street; }
set { Address = Address.WithStreet(value); }
}
//In the DbContext this property needs to be mapped with a column in a database
private int Address_Number
{
get { return Address.Number; }
set { Address = Address.WithNumber(value); }
}
#endregion
// Other properties...
// Value objects are immutables so I'm only able to replace it with a new object.
public void UpdateAddress(string street, int number)
{
Address = new Address(street, number);
}
// Other methods...
}
Run Code Online (Sandbox Code Playgroud)
EF Core 实体配置:
internal class CompanyEntityTypeConfiguration : IEntityTypeConfiguration<Company>
{
public void Configure(EntityTypeBuilder<Company> builder)
{
#region Address value object workaround
builder.Property(typeof(string), "Address_Street").HasColumnName("Address_Street");
builder.Property(typeof(int), "Address_Number").HasColumnName("Address_Number");
#endregion
}
}
Run Code Online (Sandbox Code Playgroud)
需要重写 DbContext 中的 SaveChanges()
数据库上下文:
public class YourDbContext : DbContext
{
//yours DbSet<>
protected override void OnModelCreating(ModelBuilder builder)
{
//yours EntityTypeConfiguration
}
/// <summary>
/// Overridden for value object workaround
/// </summary>
/// <returns></returns>
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries())
{
foreach (var pi in entry.Entity.GetType().GetProperties(BindingFlags.Instance | BindingFlags.NonPublic))
{
entry.Property(pi.Name).CurrentValue = pi.GetValue(entry.Entity);
}
}
return base.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
如果 ef core 2.0 拥有的实体像 EF6.X 复杂类型一样工作以实现 DDD 值对象,那就太好了。此解决方法需要一些猴子作业代码,但您将能够应用 DDD。
| 归档时间: |
|
| 查看次数: |
2557 次 |
| 最近记录: |