是否有一种方法可以清除EF缓存/本地项目,而不会对数据库造成任何改变

本文关键字:项目 任何 改变 数据库 一种 方法 EF 缓存 清除 是否 | 更新日期: 2023-09-27 18:07:13

基本上,我将EF与一个存储过程的调用混合在一起,该存储过程执行一些批量删除,否则EF太慢了。

下面是这个场景的一些伪代码(实际上我有更复杂的代码):

public void RemoveCustomer(int customerUID)
{
   // this code is running in one db transaction
   {
      // retrieve certain orders of particular customer using EF
      var orders = repoOrders.GetOrdersOfCustomer(filter, customerUID);
      // do something with above orders before deletion using EF
      repoX.DoSomethingWithOrders(orders);
      // call SP to delete all orders of customer 
      repoOrders.DeleteAllOrdersOfCustomer(customerUID);  // this calls a stored procedure
      // delete customer using EF 
      repoCustomers.DeleteCustomer(customerUID);  // throws exception due to relationship!
   }
}

当然,客户-订单是one-to-many (1:m)关系。

我想避免在上面的场景中,当有一些属于被删除的客户的上下文加载的订单时抛出的异常。例外是:

"无法更改关系,因为一个或多个外键属性不可为空。进行更改时关系时,相关的外键属性设置为空值。如果外键不支持空值,则建立新的关系必须定义,外键属性必须分配另一个非空值,否则必须删除不相关的对象。"

所以,我想知道是否有可能在调用存储过程之后和删除用户之前清除<DbSet>.Local中的一些/所有订单,而不引起对数据库的任何更改。

我想可以使用Detach,但这意味着我应该循环。

你有什么建议吗?

编辑:我是EF的新手,我现在正在使用ADO完成存储库后集成EF。NET,是的,提单一直保持不变…因此,我在这一点上尝试以最小的努力进行集成。

注意:我不能修改数据库结构

是否有一种方法可以清除EF缓存/本地项目,而不会对数据库造成任何改变

此功能从实体框架核心5开始可用!

让DbContext停止跟踪所有当前跟踪的实体:

myDbContext.ChangeTracker.Clear();

我个人会让每个存储库方法使用自己的上下文,在方法结束时保存自己的更改等,然后使用TransactionScope来确保操作是原子的。

void DeleteAllOrdersOfCustomer(Guid customerUID)
{
    using (var context = new Context())
    {
       ...
       context.SaveChanges();
    }
}

using (var ts = new TransactionScope())
{
   // call SP to delete all orders of customer 
   repoOrders.DeleteAllOrdersOfCustomer(customerUID);  // this calls a stored procedure
   // delete customer using EF 
   repoCustomers.DeleteCustomer(customerUID);  // throws exception due to relationship!
   ts.Complete();
}

可以刷新

它可能有点棘手,我不知道使用它有多贵。您将需要使用RefreshMode Enum,我假设您需要StoreWins

顺便说一句,你可能能够加速你的EF删除,而不是批处理,但这是一个不同的问题。

我一直在使用dbsetSqlQuery来达到这个目的,这样:

context.xdbset.SqlQuery("storedprocedure; select * from xdbset");  

查询调用存储过程,然后调用select *...,这在这里是必要的,因为查询结果必须包含上下文构建"xdbset"对象所需的数据格式。