Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何正确使用执行策略?_C#_Postgresql_Entity Framework_Entity Framework Core - Fatal编程技术网

C# 如何正确使用执行策略?

C# 如何正确使用执行策略?,c#,postgresql,entity-framework,entity-framework-core,C#,Postgresql,Entity Framework,Entity Framework Core,我们正在使用ExecutionStrategy,并在db上下文中使用此helper方法: public Task<T> ExecuteWithinTransactionAsync<T>(Func<IDbContextTransaction, Task<T>> operation, string operationInfo) { int counter = 0; return Database.CreateExecutionStrat

我们正在使用ExecutionStrategy,并在db上下文中使用此helper方法:

public Task<T> ExecuteWithinTransactionAsync<T>(Func<IDbContextTransaction, Task<T>> operation, string operationInfo)
{
    int counter = 0;
    return Database.CreateExecutionStrategy().ExecuteAsync(RunOperationWithinTransaction);

    async Task<T> RunOperationWithinTransaction()
    {
        counter++;
        if (counter > 1)
        {
            Logger.Log(LogLevel.Warn, $"Executing ({counter}. time) transaction for {operationInfo}.");

            ClearChangeTracker();
        }

        using (var transaction = await Database.BeginTransactionAsync(IsolationLevel.Serializable))
        {
            return await operation.Invoke(transaction);
        }
    }
}
这似乎很有效,直到我们发现一个不再有效的案例。当我们向导航属性列表添加新实体时,这些实体不会在下次尝试时被删除。比如说

var parent = context.Parents.FirstOrDefault(p => p.Id == 1);
if (parent.Children.Any()) 
{
    throw new Exception("Parent already has a child"); // This exception is thrown on the second try
}
parent.Children.Add(new Child());
context.SaveChangesAsync();
因此,如果最后一行
context.saveChangesSync()
失败,并且整个操作重新运行,
parent.Children
已经包含在
parent.Children.Add(new child())中添加的新子级我没有找到任何方法从EF中删除该项

但是,如果我们删除检查(
if(parent.Children.Any())
),如果该项已经存在或不存在,并且只尝试第二次添加它,那么它在数据库中只存储一次

我试图找出如何正确地清除DbContext,但大多数时候,答案只是创建一个新的DbContext。但是,这不是一个选项,因为ExecutionStrategy需要DbContext。这就是为什么我想知道,使用ExecutionStrategy并在每次重试时使用干净的DbContext的建议方法是什么

进一步的技术细节
  • EF核心版本:1.1.2
  • 数据库提供程序:Npgsql.EntityFrameworkCore.PostgreSQL(1.1.1)
  • 操作系统:Windows 10,在Linux中停靠
    • 在ef core 2.0.0中,引入了这种
      DbContext
      池。为了使其正常工作,
      DbContext
      实例现在可以重置其内部状态,因此可以将其作为“新”分发。可以这样调用reset方法(在
      DbContext
      中):

      所以,如果你能升级到ef core 2.0.0,那就去吧。不仅受益于这一新功能,它在许多方面都更加成熟


      免责声明:此方法仅供内部使用,因此API将来可能会更改。

      thx最终成功更新到ef core 2(由于2.0.0中的错误,不得不等待2.0.1版本),是的,它似乎正在工作。对于尝试此操作的任何其他人,
      ResetState
      实际上会处理上下文,因此您需要再次取消处理:
      ((IDbContextPoolable)this.Resurrect(((IDbContextPoolable)this.SnapshotConfiguration())
      
      var parent = context.Parents.FirstOrDefault(p => p.Id == 1);
      if (parent.Children.Any()) 
      {
          throw new Exception("Parent already has a child"); // This exception is thrown on the second try
      }
      parent.Children.Add(new Child());
      context.SaveChangesAsync();
      
      ((IDbContextPoolable)this).ResetState();