使用实体框架核心将类似一对多的嵌套实体插入数据库



我正在使用具有通用存储库模式的EF Core。

CCD_ 1表与CCD_ 2具有一对多关系。CCD_ 3是CCD_ 4中的一个外键。

POCO模型类别:

public class OrderEntity
{
public long Id { get; set; }
public long PaymentReference { get; set; }
public DateTimeOffset ModifiedDate { get; set; }
public DateTimeOffset CreatedDate { get; set; }
public IList<OrderItemEntity> OrderItemEntities { get; set; }
}
public class OrderItemEntity
{
public long Id { get; set; }
public long OrderId { get; set; }
public Position Position { get; set; }
public AlterationType Type { get; set; }
public AlterationItemType ItemType { get; set; }
public AlterationStatus Status { get; set; }
public double Measurment { get; set; }
public double AlterationCost { get; set; }
}

我的服务:

public class OrderService : Repository<OrderEntity>, IOrderService
{
public OrderService(SalesContext context) : base(context)
{
}
public long CreateOrder(OrderEntity orderEntity)
{
base.Add(orderEntity);
base.Save();
return orderEntity.Id;
}
public IEnumerable<OrderEntity> FilterOrderByFilterCriteria(long Id)
{
return base.SelectByCriteria(item => item.Id == Id);
}
public IEnumerable<OrderEntity> GetAllOrders()
{
return base.SelectAll("OrderItem");
}
}

通用存储库:

public class Repository<T> : IRepository<T> where T : class
{
private readonly SalesContext _dbContext;
public Repository(SalesContext dbContext)
{
_dbContext = dbContext;
}
public virtual T Add(T obj)
{
_dbContext.Set<T>().Add(obj);
return obj;
}
public virtual void Update(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
_dbContext.SaveChanges();
}
public virtual T Delete(T obj)
{
_dbContext.Set<T>().Remove(obj);
return obj;
}
public virtual IEnumerable<T> SelectAll(string entityToInclude)
{
return _dbContext.Set<T>().Include(entityToInclude).ToList();
}
public virtual IEnumerable<T> SelectByCriteria(Expression<Func<T, bool>> predicate)
{
return _dbContext.Set<T>().Where(predicate);
}
public virtual string Save()
{
_dbContext.SaveChanges();
return string.Empty;
}
}
}

在与数据库的同一连接中插入订单时,如何插入多个订单项?

由于OrderEntityOrderItemEntity有一对多关系,而OrderEntity有一个类型为IList<OrderItemEntity>的名为OrderItemEntities的导航属性,将该属性初始化为一个新列表,然后在将该Order1添加到数据库之前将所有子OrderItemEntity对象添加到该列表,因此它将将该列表中的所有OrderItemEntity对象与OrderEntity一起添加到数据库

public IActionResult Create(OrderWriteModel model)
{

var orderItems = new List<OrderItemEntity>();
foreach(var item in model.OrderItems)
{
OrderItemEntity orderItem = YourMappingToOrderItem(item);
orderItems.Add(orderItem);
}
OrderEntity order = YourMappingToOrder(model);
//Assign the list to the parent's property
order.OrderItemEntities = orderItems;
//This will not only create an order but also all the OrderItemEntity objects
_orderService.CreateOrder(order);
//...
}

您只需要分配给OrderEntity.OrderItemEntities。这就是你需要的全部代码。

您甚至不需要分配给外键。EF Core将自动填充所需字段。

为了方便起见,您还可以在OrderItemEntity:中包含OrderEntity导航属性

public class OrderItemEntity
{
//...
public OrderEntity OrderEntity { get; set; }
}

这是可选的。

例如,当您使用订单Id:从数据库中获取订单时

context.Orders.FirstOrDefault(o => o.Id == orderId)

这将不会填充OrderItemEntities属性,由于默认情况下不包括相关实体,因此该属性将为null。如果要包含所有OrderItemEntity,请将呼叫链接到Include():

context.Orders
.Include(o => o.OrderItemEntities)
.FirstOrDefault(o => o.Id == orderId)

这将包括所有的孩子。

如果您调用OrderItem0,以下项目将插入订单旁边;

var newOrderId = CreateOrder(new OrderEntity (){
...
OrderItemEntities  = new List<OrderItemEntity> (){new OrderItemEntity{...}},
...
});

旁注:(独立于EF,但肯定是appies(。。集合属性(例如IList(不应为null,它们应始终在创建对象时初始化。