简体   繁体   English

实体框架不会保存不同注入的 dbContext 中的更改

[英]Entity Framework won't save changes in different injected dbContext

The problem:问题:

Changes to Orders aren't being saved to the DB when a dbcontext injected into CustomersRepository is used before adding an Order using the OrdersRepository在使用 OrdersRepository 添加订单之前使用注入到 CustomersRepository 的 dbcontext 时,对订单的更改不会保存到数据库中

Setup Details设置细节

Latest C#, .net 6.0, EF 6.0, SQL Server running on local machine.最新 C#、.net 6.0、EF 6.0、SQL 在本地计算机上运行的服务器。 I'm using a variation on Clean Architecture.我正在使用 Clean Architecture 的变体。 I have 2 different repositories: CustomersRepository and OrdersRepository.我有 2 个不同的存储库:CustomersRepository 和 OrdersRepository。 Each one injects a dbContext.每个注入一个 dbContext。 All injected dependencies use Scoped: services.AddScoped<ICustomersRepository, CustomersRepository>();所有注入的依赖项都使用 Scoped: services.AddScoped<ICustomersRepository, CustomersRepository>();

The problem Code问题代码

// this first line is the problem
var currentCustomer = await customersRepository.GetCustomer(int id); // remove this line and it saves to the DB when CreateOrder() is called. Why??

var newOrder = new Order() { CustomerId = currentCustomer.Id };
var orderId = await ordersRepository.CreateOrder(newOrder); // doesn't save to db here or throw any error.
await customersRepository.SaveCustomer(currentCustomer); // saves the newOrder to the db here, or errors if newOrder is invalid. 

CustomersRepository客户资料库

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="dbContext"></param>
        public CustomersRepository(ApplicationDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public async Task<int> SaveCustomer(Customer customer)
        {
            dbContext.Customers.Update(customer);            

            await dbContext.SaveChangesAsync();
            return customer.Id;
        }

OrdersRepository订单库

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="dbContext"></param>
        public OrdersRepository(ApplicationDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public async Task<int> CreateOrder(Order order)
        {
            await dbContext.Orders.AddAsync(order);
            await dbContext.SaveChangesAsync();
            return order.Id;
        }

What is expected什么是预期的

  • Why do I have to call customersRepository.SaveCustomer() to save an Order?为什么我必须调用customersRepository.SaveCustomer()来保存订单?
  • What is the correct way to save the Order, or what am I doing wrong?保存订单的正确方法是什么,或者我做错了什么?
  • If I don't retrieve the currentCustomer, it works as expected and ordersRepository.CreateOrder() adds the new order to the db (or errors).如果我没有检索到 currentCustomer,它将按预期工作并且ordersRepository.CreateOrder()将新订单添加到数据库(或错误)。
  • If I don't call customersRepository.SaveCustomer() nothing is changed in the db and no sql errors are thrown.如果我不调用customersRepository.SaveCustomer() ,数据库中没有任何更改,也不会抛出 sql 错误。
  • I want to clarify that an order doesn't have to belong to a customer, it's optional.我想澄清一下,订单不一定属于客户,它是可选的。

Figured it out... The reason it wasn't saving is because I tied the Customer to the Order by setting newOrder.CustomerId = xxx.想通了......它没有保存的原因是因为我通过设置 newOrder.CustomerId = xxx 将客户绑定到订单。

The problem is this:问题是这样的:

  1. EF started tracking currentCustomer once I retrieved it from the db.我从数据库中检索到 currentCustomer 后,EF 开始跟踪它。
  2. After creating the new Order I assigned the newOrder.CustomerId = currentCustomer.Id.创建新订单后,我分配了 newOrder.CustomerId = currentCustomer.Id。
  3. When I called dbContext.SaveChangesAsync(newOrder) , EF noticed the dependency between the currentCustomer and the newOrder since currentCustomer was still in the dbContext.当我调用dbContext.SaveChangesAsync(newOrder)时,EF 注意到 currentCustomer 和 newOrder 之间的依赖关系,因为 currentCustomer 仍在 dbContext 中。
  4. When this happens, EF is smart enough to know the currentCustomer needs to be updated at the same time so the newOrder is assigned to it.发生这种情况时,EF 足够聪明,知道 currentCustomer 需要同时更新,因此将 newOrder 分配给它。 EF then puts the newOrder in a "Detached" state. When this happens no query is ran. EF 然后将 newOrder 放入"Detached" state。发生这种情况时,不会运行任何查询。 Thus nothing happens - no errors, no success... yet.因此什么也没有发生——没有错误,没有成功……但是。
  5. Finally I call dbContext.Update(currentCustomer) which automagically changes the state of the newOrder to "Added" .最后我调用dbContext.Update(currentCustomer)自动将 newOrder 的 state 更改为"Added"
  6. At this point I can call dbContext.SaveChangesAsync() and both the newOrder and the currentCustomer are updated to the DB in the same transaction (EF does the transaction automatically).此时我可以调用dbContext.SaveChangesAsync()并且 newOrder 和 currentCustomer 都更新到同一事务中的数据库(EF 自动执行事务)。 I think it behaves this way to avoid orphaning a record, in my case, orphaning the new Order record.我认为这样做是为了避免孤立记录,在我的例子中,是孤立新的订单记录。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM