这是我为C#控制台应用程序设计的(非常简化以说明问题空间)设计。数据库连接实现IDisposable,此解决方案不允许using
数据库连接对象。有人可以为控制台应用程序提出更正确的结构吗?这是我经常需要解决的问题。
class Program
{
SQLiteConnection sourceConnection;
SQLiteConnection destinationConnection;
static void Main(string[] args)
{
Program shell = new Program();
// get connection strings from command line arguments
string sourceConnectionString = shell.getConnectionString(args);
string destinationConnectionString = shell.getConnectionString(args);
// call non-static methods that use
shell.setUpConnections(sourceConnectionString, destinationConnectionString);
shell.doDatabaseWork();
}
private void setUpConnections(string sourceConnectionString, string destinationConnectionString)
{
sourceConnection = new SQLiteConnection(sourceConnectionString);
destinationConnection = new SQLiteConnection(destinationConnectionString);
}
private void doDatabaseWork()
{
// use the connections here
}
}
修改
有些人无法弄清楚为什么我要将它们作为成员变量。这是doDatabaseWork中的用例(有点伪装):
foreach (Row sourceRow in DBResultSet)
{
string sourceXml = sourceRow.Columns["MyColumnName"].Value;
string destinationXML = transformUsingXSLT(sourceXml);
writeToDestination(destinationXml);
}
看看我想如何在这个循环的生命周期中保持这些连接打开?
答案 0 :(得分:6)
如何编写实现IDisposable的类。
在类构造函数中,您可以实例化数据库连接。
然后在IDisposable.Dispose方法中,编写用于关闭数据库连接的拆卸代码。
这是一个代码示例,用于演示我的意思:
public class DBWrapper : IDisposable
{
public SqlConnection Connection1 { get; set; }
public SqlConnection Connection2 { get; set; }
public DBWrapper()
{
Connection1 = new SqlConnection();
Connection1.Open();
Connection2 = new SqlConnection();
Connection2.Open();
}
public void DoWork()
{
// Make your DB Calls here
}
public void Dispose()
{
if (Connection1 != null)
{
Connection1.Dispose();
}
if (Connection2 != null)
{
Connection2.Dispose();
}
}
}
然后,从您的Program类的main方法中:
class Program
{
static void Main(string[] args)
{
using (DBWrapper wrapper = new DBWrapper())
{
wrapper.DoWork();
}
}
}
答案 1 :(得分:2)
static void Main(string[] args)
{
Program shell = new Program();
// get connection strings from command line arguments
string sourceConnectionString = shell.getConnectionString(args);
string destinationConnectionString = shell.getConnectionString(args);
// call non-static methods that use
shell.setUpConnections(sourceConnectionString, destinationConnectionString);
try
{
shell.doDatabaseWork();
}
finally
{
if(sourceConnection != null)
sourceConnection.Dispose();
if(destinationConnection != null)
destinationConnection.Dispose();
}
}
答案 2 :(得分:2)
就个人而言,我认为你是在考虑这个,这个帖子中的代码示例过于复杂了。我不知道为什么人们在他们的Program类上实现IDisposable,因为它在退出时被处理掉了。
我想不出一个不使用的理由或为什么你不能使用using(){}语句。
你想打开一个连接并持有它吗?为什么?所有真正的连接都在.net连接池的幕后,所以新的Connection对象并不是什么大问题。只需在需要时打开和关闭,连接池就可以处理幕后的所有内容。
我编辑了我的示例以将其包装在一个类中,因此您也可以进行封装。
class Program
{
static void Main(string[] args)
{
DBWorker worker = new DBWorker();
worker.DoDatabaseWork();
}
}
public class DBWorker
{
private void DoDatabaseWork()
{
using (SQLiteConnection sourceDB = new SQLiteConnection( GetConnectionString() ))
{
sourceDB.Open();
using (SQLiteConnection destDB = new SQLiteConnection( GetConnectionString() ))
{
destDB.Open();
}
}
}
}
答案 3 :(得分:2)
我认为最好的解决方案是从Program类中提取主逻辑。 Program类是主要工作的某种启动器。并且为SqlConnections提供包装器确实不是一个好主意,因为它们已经是托管资源,包装它们是多余的。因此,我的解决方案如下所示:
class ProgramCore : IDisposable
{
internal ProgramCore(string sourceConnectionString, string destinationConnectionString)
{
setUpConnections(sourceConnectionString, destinationConnectionString);
}
internal void Execute()
{
// do whatever you want
doDatabaseWork();
// do whatever you want
}
public void Dispose()
{
if (_sourceConnection != null)
_sourceConnection.Dispose();
if (_destinationConnection != null)
_destinationConnection.Dispose();
}
private void setUpConnections(string sourceConnectionString, string destinationConnectionString)
{
_sourceConnection = new SQLiteConnection(sourceConnectionString);
_destinationConnection = new SQLiteConnection(destinationConnectionString);
}
private void doDatabaseWork()
{
// use the connections here
}
private SQLiteConnection _sourceConnection;
private SQLiteConnection _destinationConnection;
}
class Program
{
static void Main(string[] args)
{
// get connection strings from command line arguments
string sourceConnectionString = GetConnectionString(args);
string destinationConnectionString = GetConnectionString(args);
using (ProgramCore core = new ProgramCore(sourceConnectionString, destinationConnectionString))
{
core.Execute();
}
}
static string GetConnectionString(string[] args)
{
// provide parsing here
}
}
答案 4 :(得分:0)
using
中使用的变量。
class Program
{
SQLiteConnection sourceConnection;
SQLiteConnection destinationConnection;
static void Main(string[] args)
{
Program shell = new Program();
// get connection strings from command line arguments
string sourceConnectionString = shell.getConnectionString(args);
string destinationConnectionString = shell.getConnectionString(args);
using (sourceConnection = new SQLiteConnection(sourceConnectionString))
using (destinationConnection = new SQLiteConnection(destinationConnectionString))
{
shell.doDatabaseWork();
}
}
private void doDatabaseWork()
{
// use the connections here
}
}