【发布时间】:2015-03-27 08:23:22
【问题描述】:
我正在编写一个与底层数据库进行交互的服务类。我在类构造函数中将连接作为参数传递。
public class MyDbService : IDbService
{
private readonly IDbConnection _connection;
public MyDbService(IDbConnection connection)
{
_connection = connection;
}
public void DoStuff()
{
// Sql-Server implementation
var conn = _connection as SqlConnection;
if(conn != null)
{
using(conn)
{
conn.Open();
// Do stuff
}
}
// Implementation for other providers
...
}
}
DoStuff() 在第一次被调用时工作,但由于using() 子句,conn 对象被释放,当再次调用conn.Open() 时我得到一个InvalidOperationException。
我可以通过删除using 并添加conn.Close() 来解决这个问题,但这对我来说似乎是一个“丑陋”的选择?
所以,我有两个问题,第一个是 oop 的基础:
- 为什么在我使用
using(conn)时会释放_connection对象? - 在构造函数中传递连接对象时,什么是“最佳实践”?
编辑:
该类是 WPF 应用程序的一部分。
由于问题似乎与 DI 有关,我已经概述了背后的类。我明白了,我需要传入连接对象的一个新实例,因为它在服务中第一次使用后被处理 - 我只是看不到如何(至少在没有将 Unity 容器携带到视图模型和手动解决)。当然,一个非常简单的解决方案是将连接字符串和提供程序传递给服务构造函数,但我想让这种方法以某种方式工作。任何提示都非常感谢:)
App.xaml.cs:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var connString = System.Configuration.ConfigurationManager.ConnectionStrings["LocalTest"].ConnectionString;
var providerName = System.Configuration.ConfigurationManager.ConnectionStrings["LocalTest"].ProviderName;
var connection = DbProviderFactories.GetFactory(providerName).CreateConnection();
if (connection != null)
{
connection.ConnectionString = connString;
var myService= new MyDbService(connection);
// Register dependency injection
var container = new UnityContainer();
container.RegisterInstance<IDbConnection>(connection);
container.RegisterInstance<IDbService>(myService);
var mainWindow = container.Resolve<MainWindow>();
mainWindow.Show();
}
else
{
// Handle null connection
}
}
}
MainWindow.xaml.cs:
public partial class MainWindow: Window
{
private MyViewModel _vm;
public MainWindow()
{
InitializeComponent();
}
[Dependency]
public MyViewModel ViewModel
{
set
{
_vm = value;
DataContext = _vm;
}
}
}
MyViewModel.cs:
public class MyViewModel: INotifyPropertyChanged
{
private readonly IDbService _dbService;
public MyViewModel(IDbService dbService)
{
_dbService = dbService;
}
public void DoStuff()
{
_dbService.DoStuff();
}
...
// Other viewmodel stuff
}
【问题讨论】:
-
您是否使用
Singleton()生命周期创建连接? -
我像这样创建连接:
var connection = DbProviderFactories.GetFactory(providerName).CreateConnection()并通过 Unity DI 传递它 -
你确定,每次你通过 IDbConnection- 都是新的连接吗?当你第二次调用
DoStuff()时,看起来你从第一次传递到这里的 IDbConnection 已经被处理了。