【发布时间】:2019-08-29 07:58:06
【问题描述】:
我有以下课程:
订单:
public class Order {
private Order()
{
//some code to initialise object
}
//more properties
public Prepayment Prepayment { get; private set; }
//more methods and properties
}
预付款:
public class Prepayment:ValueObject<Prepayment>
{
private Prepayment()
{
}
public Money AmountPrepaid { get; private set; }
public bool HasPrepaymentBeenTaken => AmountPrepaid.Amount > 0;
}
金钱:
public class Money {
private Money()
{
}
private Money(decimal amount)
: this()
{
Amount = amount;
}
public decimal Amount { get; private set; }
}
然后我将 Order 类通过以下方式映射到数据库:
modelBuilder.Entity<Order>()
.OwnsOne(x => x.Prepayment,
prepayment =>
{
prepayment.OwnsOne(x => x.AmountPrepaid,
amountPrepaid =>
{
amountPrepaid.Property(x => x.Amount)
.HasColumnName("PrepaymentAmount")
.HasColumnType("decimal(7,2)");
});
});
SaveChanges 的存储库代码:
public async Task<int> SaveAsync(Order order)
{
if (order.Id == 0)
{
await _context.AddAsync(order);
}
else
{
_context.Update(order);
}
return await _context.SaveChangesAsync();
}
请理解,我从代码中删除了所有不重要的属性,以使示例更清晰。
以上代码适用于INSERT 场景,其中预付款 -> 货币 -> 金额已正确保存到数据库中。 UPDATE 虽然似乎没有反映在数据库中。
请注意,我在该模型中有很多 Owned Types,并且它们都运行良好。据我所知,唯一的区别是 Prepayment 属性有另一个嵌套的 Owned 类型 - Money。
Order 类对象传递到存储库,首先从数据库中提取,然后将更改应用于该实例,最后保存回数据库。示例中未提及的其他属性(例如 Customer)也是 OwnedType 和 UPDATE 按预期工作。
以防万一 - 用于在更新之前检索对象的代码:
public async Task<Order> GetOrderByIdAsync(int orderId)
{
var result = (from order in _context.Orders
where order.Id == orderId
select order).Include(x => x.OrderLines);
return await result.FirstOrDefaultAsync();
}
我使用的 Entity Framework Core 的确切版本是:2.2.0
任何帮助将不胜感激。 谢谢。
编辑:
更新数据的代码如下所示:
public async Task<int> Handle(EditOrderCommand request, CancellationToken cancellationToken)
{
var order = await _orderRepository.GetOrderByIdAsync(request.Id);
var customer = new Customer(
request.FirstName,
request.LastName,
request.TelephoneNumber);
var prepayment = new Prepayment(
Money.SomeMoney(
request.PrepaymentAmount
)
);
order.ApplyChanges(
request.UserId,
request.AdditionalInformation,
collectionDate,
customer,
prepayment);
await _orderRepository.SaveAsync(order);
return order.Id;
}
以及设置预付款的部分 ApplyChanges 方法:
private void SetPrepayment(Prepayment prepayment)
{
Prepayment = prepayment ?? throw new ArgumentNullException(nameof(prepayment));
}
【问题讨论】:
-
对象是否从用于
Update的相同 db 上下文实例中提取?修改了什么以及如何修改?所有这些私有构造函数/属性设置器让我觉得你在做一些不寻常/不被 EF Core 预期/支持的事情。提供一个小而完整的重现 (mcve) 将有助于识别问题。 -
是的。我也尝试在更新之前执行 _context.Attach ,但根本没有改变。私有设置器也运行良好,Orders 对象上有一个更改预付款状态的方法。我在 Order 类上还有另一种行为正常的自有类型,据我所知,doffference 是嵌套的。预付款在其中嵌套了 Money 对象。
-
如果它是从同一个数据库上下文实例中提取的,则它已经附加,因此通常不需要
Attach和Update。当然,你有一些变异方法,问题是它们做了什么。简单来说,它们是修改现有对象的属性还是创建新对象? DDD“值对象”看起来很可疑。看起来需要minimal reproducible example。 -
我现在知道了,它只是将新的 Prepayment 对象分配给 Order 值。 Prepayment 或 Money 甚至没有 Id 字段,因为它们是自有类型。作为比较,还有另一个 Property Customer - 具有 ValueObject
的私有设置器,并且每次都设置 Customer 的新实例 - 并且按预期工作。如果有机会,我会在下午晚些时候尝试准备一个示例。我现在放置了处理程序代码 - 保存更改并应用更新 -
有一个bug in ef core 2.2 阻止自有类型的更新。您找到解决方法了吗?
标签: c# ef-core-2.2