c# - 如何一次添加多个实体和孩子
问题描述
我在 foreach 循环中一次添加具有多个子项的多个实体时遇到问题。
其明显的 ef 无法在 foreach 循环中跟踪 id。但也许还有其他解决方案可以指导我。
当我尝试将多个实体与孩子一起添加时的错误是:
无法跟踪实体类型的实例,因为已经在跟踪具有与 {'Id'} 相同键值的另一个实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。
例如:
public class Order
{
public Order()
{
OrderDetails = new HashSet<OrderDetail>();
}
[Key]
public int Id { get; set; }
[StringLength(50)]
public string Code { get; set; }
public int? CompanyId { get; set; }
public int? PartnerId { get; set; }
public decimal TotalNetPrice { get; set; }
public decimal TotalPrice { get; set; }
public bool IsActive { get; set; } = true;
public bool IsDeleted { get; set; } = false;
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[ForeignKey("PartnerId")]
public virtual Partner Partner { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get; set; }
}
public class OrderDetail
{
[Key]
public int Id { get; set; }
public int OrderId { get; set; }
[StringLength(50)]
public string Code { get; set; }
public int LineNumber { get; set; }
public int ProductId { get; set; }
public int Quantity { get; set; }
public bool IsActive { get; set; } = true;
public bool IsDeleted { get; set; } = false;
[ForeignKey("OrderId")]
public virtual Order Order { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
}
这是我在方法中的代码:
foreach (var order in orderList)
{
// consider we create/cast object to Order class.
_orderService.Add(order);
// in here we don't have id, because we didn't call savechanges.
foreach(var orderDetail in order.orderDetailList)
{
// consider we create/cast object to OrderDetail class.
orderDetail.orderId = order.Id;
// in here, order id is always 0 as expected.
_order.OrderDetails.Add(orderDetail);
}
}
try
{
await uow.SaveChangesAsync();
}
catch(Exception exception)
{
var msg = exception.Message;
}
我尝试对[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
标识列使用属性。
根据文档(https://docs.microsoft.com/en-us/ef/core/modeling/generated-properties?tabs=data-annotations):
根据所使用的数据库提供程序,值可能由 EF 或在数据库中生成客户端。如果该值是由数据库生成的,那么 EF 可能会在您将实体添加到上下文时分配一个临时值。然后,此临时值将被 SaveChanges() 期间数据库生成的值替换。
所以它应该至少提供临时 ID 来跟踪它。但它不适用于我的情况。
我还尝试了相同的方法来创建上下文中的模型。但同样的结果。没有成功。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity>()
.Property(x => x.Id)
.ValueGeneratedOnAdd();
}
似乎最好的解决方案是在详细信息之前进行交易并保存订单并获取真实ID,然后添加详细信息。但如您所知,它存在性能问题。
我想知道这个问题是否还有其他最佳实践?
谢谢你。
解决方案
尝试这个:
foreach (var order in orderList)
{
_orderService.Add(order);
foreach(var orderDetail in order.orderDetailList)
{
// Add reference Of Order to OrderDetails, not an id
orderDetail.Order = order;
_order.OrderDetails.Add(orderDetail);
}
}
在这种情况下,EF 将知道如何在 SaveChangesAsync 上连接 Order 和 OrderDetail
推荐阅读
- java - Thymeleaf - 一次加载元数据并在所有页面中使用
- android - Android 上内容过长时的 vCard 导入问题
- python - 如何使用 xlsxwriter 以英寸为单位设置行高?
- swift - 来自字符串的 Swift DateFormatter 日期在 NSDateFormatter 曾经工作的地方失败
- php - 将应用程序升级到 CodeIgniter 3 后出现问题
- c++ - 为什么我不能在循环中更改指针的内容?
- java - Apache Axis1 与 JDK11 的兼容性
- python - 绘制 Benford 定律的直方图
- facebook-graph-api - Facebook 图形 API:群组帖子评论中的数据缺失
- flowground - 无法从“request-reply”模块中获取 arrey