使用C#10,.NET 6和EF Core 6更改嵌套值对象的值的问题
我的汇总是这样的:
public class Order : AggregateRoot
{
private readonly List<OrderItem> _items = new();
public DateTime Date { get; set; }
public IReadOnlyCollection<OrderItem> Items => _items;
public void SetItemDiscounts(int itemId, IEnumerable<Discount> discounts)
{
var orderItem = _items.Single(item => item.Id == itemId);
orderItem.SetDiscounts(discounts);
}
}
public class OrderItem : Entity
{
private readonly List<Discount> _discounts = new();
public int OrderId { get; private set; }
public int Qty { get; private set; }
public Money Price { get; private set; }
public IReadOnlyCollection<Discount> Discounts => _discounts;
public void SetDiscounts(IEnumerable<Discount> discounts)
{
_discounts.Clear();
_discounts.AddRange(discounts);
}
}
public class Discount : ValueObject<Discount>
{
public int Plan { get; private set; }
public Money Amount { get; private set; }
}
public class Money : ValueObject<Money>
{
public int CurrencyId { get; private set; }
public decimal Value { get; private set; }
}
EF核心的配置是:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>().HasKey(x => x.Id);
modelBuilder.Entity<Order>().Property(t => t.Id)
.HasColumnType(nameof(SqlDbType.BigInt)).IsRequired();
modelBuilder.Entity<Order>().Property(t => t.Date)
.HasColumnType(nameof(SqlDbType.DateTime2)).IsRequired();
modelBuilder.Entity<Order>().HasMany<OrderItem>().WithOne()
.HasForeignKey(x => x.OrderId);
modelBuilder.Entity<OrderItem>().HasKey(x => x.Id);
modelBuilder.Entity<OrderItem>().Property(t => t.Id)
.HasColumnType(nameof(SqlDbType.Int)).IsRequired();
modelBuilder.Entity<OrderItem>().Property(t => t.Qty)
.HasColumnType(nameof(SqlDbType.Int)).IsRequired();
modelBuilder.Entity<OrderItem>().OwnsOne(x => x.Price)
.Property(x => x.Value).HasColumnType(nameof(SqlDbType.Decimal))
.HasColumnName("Price").IsRequired();
modelBuilder.Entity<OrderItem>().OwnsMany(
orderItem => orderItem.Discounts,
discountNavigationBuilder =>
{
discountNavigationBuilder.Property(p => p.Plan)
.HasColumnType(nameof(SqlDbType.Int)).IsRequired();
discountNavigationBuilder.OwnsOne(
discount => discount.Amount,
amountNavigationBuilder =>
{
amountNavigationBuilder.Property(p => p.CurrencyId)
.HasColumnType(nameof(SqlDbType.Int)).HasColumnName("CurrencyId").IsRequired();
amountNavigationBuilder.Property(p => p.Value)
.HasColumnType(nameof(SqlDbType.Decimal)).HasColumnName("Amount").IsRequired();
});
});
}
当我创建带有项目和折扣的订单时没有问题,但是当我使用setDiscounts方法更新折扣时,我会遇到此错误:
system.invalidoperationException:属性:属性'Discount.amount#Money.discountid'是密钥的一部分,因此无法修改或标记为修改。要将现有实体的本金与识别外键更改,请首先删除因子并调用“ savechanges”,然后将依赖人与新的本金相关联。
这里的折扣是什么?我的配置或任何其他代码有什么问题吗?
My Aggregate is like this:
public class Order : AggregateRoot
{
private readonly List<OrderItem> _items = new();
public DateTime Date { get; set; }
public IReadOnlyCollection<OrderItem> Items => _items;
public void SetItemDiscounts(int itemId, IEnumerable<Discount> discounts)
{
var orderItem = _items.Single(item => item.Id == itemId);
orderItem.SetDiscounts(discounts);
}
}
public class OrderItem : Entity
{
private readonly List<Discount> _discounts = new();
public int OrderId { get; private set; }
public int Qty { get; private set; }
public Money Price { get; private set; }
public IReadOnlyCollection<Discount> Discounts => _discounts;
public void SetDiscounts(IEnumerable<Discount> discounts)
{
_discounts.Clear();
_discounts.AddRange(discounts);
}
}
public class Discount : ValueObject<Discount>
{
public int Plan { get; private set; }
public Money Amount { get; private set; }
}
public class Money : ValueObject<Money>
{
public int CurrencyId { get; private set; }
public decimal Value { get; private set; }
}
And the configuration for EF Core is:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>().HasKey(x => x.Id);
modelBuilder.Entity<Order>().Property(t => t.Id)
.HasColumnType(nameof(SqlDbType.BigInt)).IsRequired();
modelBuilder.Entity<Order>().Property(t => t.Date)
.HasColumnType(nameof(SqlDbType.DateTime2)).IsRequired();
modelBuilder.Entity<Order>().HasMany<OrderItem>().WithOne()
.HasForeignKey(x => x.OrderId);
modelBuilder.Entity<OrderItem>().HasKey(x => x.Id);
modelBuilder.Entity<OrderItem>().Property(t => t.Id)
.HasColumnType(nameof(SqlDbType.Int)).IsRequired();
modelBuilder.Entity<OrderItem>().Property(t => t.Qty)
.HasColumnType(nameof(SqlDbType.Int)).IsRequired();
modelBuilder.Entity<OrderItem>().OwnsOne(x => x.Price)
.Property(x => x.Value).HasColumnType(nameof(SqlDbType.Decimal))
.HasColumnName("Price").IsRequired();
modelBuilder.Entity<OrderItem>().OwnsMany(
orderItem => orderItem.Discounts,
discountNavigationBuilder =>
{
discountNavigationBuilder.Property(p => p.Plan)
.HasColumnType(nameof(SqlDbType.Int)).IsRequired();
discountNavigationBuilder.OwnsOne(
discount => discount.Amount,
amountNavigationBuilder =>
{
amountNavigationBuilder.Property(p => p.CurrencyId)
.HasColumnType(nameof(SqlDbType.Int)).HasColumnName("CurrencyId").IsRequired();
amountNavigationBuilder.Property(p => p.Value)
.HasColumnType(nameof(SqlDbType.Decimal)).HasColumnName("Amount").IsRequired();
});
});
}
There is no problem when I create an order with Items and discounts, but while I update discounts using SetDiscounts method I get this error :
System.InvalidOperationException: The property 'Discount.Amount#Money.DiscountId' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key, first delete the dependent and invoke 'SaveChanges', and then associate the dependent with the new principal.
What is DiscountId here? Is there any problem with my configuration or any other code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在EF核心中进行了一些搜索和研究之后,我发现有一个价值对象的功能。我更改了代码,它的工作原理很好:
我写了一个类的前值转换:
我将EF配置更改为:
After some search and study in EF-Core I found that there is a feature for ValueObjects. I changed the code and it works really fine:
I wrote a class fore value conversion:
And I changed Ef configuration to :