.NET Core中IDisposable类的依赖注入生命周期

5
我想知道,在请求完成后,处理所有IDisposable对象的最佳方法是什么。
  • AddTransient<T> - 添加一个类型,每次请求时都会重新创建。
  • AddScoped<T> - 添加一个类型,保留请求的范围。
  • AddSingleton<T> - 添加一个类型,当第一次请求时就会创建并保持它。

因此,单例可能不是一个好选择,因为它在应用程序关闭后将被处理。但作用域和瞬态是很好的选择。我有一个存储库,我想像这样创建与我的数据库连接:

public class Dapperr : IDapper  
    {  
        private readonly IConfiguration _config;  
        private string Connectionstring = "DefaultConnection";  
  
        public  Dapperr(IConfiguration config)  
        {  
            _config = config;  
        }  
        public void Dispose()  
        {  
             
        }  
  
        
        public T Get<T>(string sp, DynamicParameters parms, CommandType commandType = CommandType.Text)  
        {  
            using IDbConnection db = new SqlConnection(_config.GetConnectionString(Connectionstring));  
            return db.Query<T>(sp, parms, commandType: commandType).FirstOrDefault();  
        }  
  
        public List<T> GetAll<T>(string sp, DynamicParameters parms, CommandType commandType = CommandType.StoredProcedure)  
        {  
            using IDbConnection db = new SqlConnection(_config.GetConnectionString(Connectionstring));  
            return db.Query<T>(sp, parms, commandType: commandType).ToList();  
        }  
}

现在我要在我的创业公司中添加依赖注入:

services.AddScoped<IDapper, Dapperr>();

我想知道如果我添加了作用域依赖,是否可以删除所有这些using作用域?例如:

public class Dapperr : IDapper  
    {  
        private readonly IConfiguration _config;  
        private string Connectionstring = "DefaultConnection";  
    private readonly IDbConnection db ;
        public  Dapperr(IConfiguration config)  
        {  
            _config = config;
         db = new SqlConnection(_config.GetConnectionString(Connectionstring));  
        }  
        
        
        public T Get<T>(string sp, DynamicParameters parms, CommandType commandType = CommandType.Text)  
        {  
            
            return db.Query<T>(sp, parms, commandType: commandType).FirstOrDefault();  
        }  

        public List<T> GetAll<T>(string sp, DynamicParameters parms, CommandType commandType = CommandType.StoredProcedure)  
        {  
             
            return db.Query<T>(sp, parms, commandType: commandType).ToList();  
        }
  
    }

SQL连接在请求结束后是否被释放,还是我需要继续使用“using”?

2
DI容器只会处理它自己创建的实例。你需要在Dapperr构造函数中手动创建SqlConnection实例,DI容器不会处理该实例的释放。你需要手动调用Dispose方法来释放SqlConnection实例。最明显的调用Dispose方法的地方是在Dapperr.Dispose方法中。 - Steven
@Steven,为什么Entity Framework在实现IDisposable接口时没有使用using或dispose?你确定吗? - Ali Eshghi
3
如果你的类内部创建了一次性的对象(比如 SQL 连接),那么你的类应该实现 IDisposable 接口,并根据释放模式清理资源。依赖注入框架会识别你的类实现了该接口,并在作用域关闭时调用 Dispose() 方法。 - Oliver
1
Oliver是正确的。在您引用的示例中,DataContext被注入到DatingRepository中,并由DI容器管理。这就是为什么如果它实现了IDisposable,DI容器将处理DataContext的释放。在您的问题中,SqlConnection不受DI容器管理,而是由您在代码中手动创建。 - Steven
非常感谢你们两位。 - Ali Eshghi
显示剩余2条评论
1个回答

1

阅读评论后,我了解到必须将接口设置为IDisposable以释放连接,因此我将代码更改如下:

public interface IDapper : IDisposeable
{
    ... 
}

然后在我的代码库中,我实现了dispose方法:

public class Dapperr : IDapper  
{  
    private readonly IConfiguration _config;  
    private string Connectionstring = "DefaultConnection";  
    private readonly IDbConnection db;
    
    public  Dapperr(IConfiguration config)  
    {  
        _config = config;
        db = new SqlConnection(_config.GetConnectionString(Connectionstring));
    }  
    
    public T Get<T>(
        string sp,
        DynamicParameters parms,
        CommandType commandType = CommandType.Text)  
    {  
        return db.Query<T>(sp, parms, commandType: commandType).FirstOrDefault();  
    }  

    public List<T> GetAll<T>(string sp, DynamicParameters parms) =>
        db.Query<T>(sp, parms, commandType: commandType).ToList();  
    
    public void Dispose()
    {
        db?.dispose(); 
    }
}

调试后,我发现调用了Dispose方法并释放了连接。我不确定这是否是最佳实践,但通过这些更改,我只写了一次连接配置,并删除了所有的using块。我认为这对于轻量级请求来说是很好的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接