这是我的“包含”第一次没有带回实体。不知道还缺什么
比林斯班
public Order Order { get; set; }
public List<BillingItem>? BillingItems { get; set; }
应用程序数据库上下文
modelBuilder.Entity<Billing>()
.HasOne(e => e.Order)
.WithOne(e => e.Billing)
.HasForeignKey<Billing>(e => e.OrderID)
.OnDelete(DeleteBehavior.Restrict);
您的代码示例(未显示)做错了几件事。基本上,您正在创建一个新的 Billing 实例(很好),然后加载一个订单(好的),然后单独加载该订单的订单项目(不理想),然后将订单的 orderItems 集合设置为加载的订单项目(红色警报,不做)。从那里,您可以使用传递的订单在新的计费实例上调用一些 CreateFromOrder 方法,然后附加计费(不,不适用于插入)并调用 SaveChanges。
var billing await db.Billings
.Include(b => b.Order)
.ThenInclude(o => o.OrderItems)
.SingleOrDefaultAsnc(b => b.OrderId == orderId && b.Status != Status.Deleted);
if(billing != null)
{
billing = new Billing();
order = await db.Orders
.Include(o => o.OrderItems)
.SingleAsync(o => o.Id == orderId && o.Status != Status.Deleted);
billing.CreateFromOrder(order);
db.Billings.Add(billing);
await db.SaveChangesAsync();
}
我们不需要在插入后尝试重新加载账单,我们可以在开始时获取任何现有的账单。如果我们没有得到一个,创建一个新的,加载订单,急切加载订单项目,然后将其与新的账单相关联,重要的是使用
DbSet.Add()
而不是 Attach()
来确保 EF 知道这是一个新的账单.
如果我们只是想检查账单是否不存在,那么我们不需要加载它,我们可以只进行存在检查 /w
.Any()
:
var billingExists db.Billings
.Any(b => b.OrderId == orderId && b.Status != Status.Deleted);
if(billing != null)
{
Billing billing = new Billing();
...
我强烈建议在导航属性方面避免错误的一个重要更改是,无论您拥有集合导航属性(例如 Order.OrderItems),您都应该不拥有可访问的设置器。例如,像
order.OrderItems = orderItems
这样的代码非常糟糕,因为更改跟踪器将有一个代理来通知何时添加/删除集合项以及当您重新分配集合时,该代理会被破坏。
代替:
public ICollection<OrderItem> OrderItems { get; set; }
集合导航属性应声明为:
public virtual ICollection<OrderItem> OrderItems { get; } = [];
// or
public virtual ICollection<OrderItem> OrderItems { get; protected set; } = new List<OrderItem>(); // for older C# versions.
任何代码都不应该在初始化后设置集合导航属性。