我似乎有两个选择:
IDisposable
。将我的DbCommand
个实例创建为private readonly
个字段,并在构造函数中添加它们使用的参数。每当我想写入数据库时,绑定到这些参数(重用相同的命令实例),设置Connection
和Transaction
属性,然后调用ExecuteNonQuery
。在Dispose
方法中,在每个字段上调用Dispose
。using(var cmd = new DbCommand("...", connection, transaction))
,并在调用ExecuteNonQuery
之前每次添加参数并绑定它们。我假设我不需要为每个查询创建一个新命令,每次打开数据库时都只需要一个新命令(对吗?)。这些都看起来有点不雅,可能不正确。
对于#1,我的用户觉得我这个类现在IDisposable
只是因为我使用了一些DbCommand
(这应该是他们不关心的实现细节)关于)。我也有点怀疑保留一个DbCommand
实例可能会无意中锁定数据库或什么东西?
对于#2,每次我想写入数据库时,感觉就像我在做很多工作(就.NET对象而言),尤其是参数添加。我似乎每次都创建相同的对象,这感觉就像是不好的做法。
供参考,这是我当前的代码,使用#1:
using System;
using System.Net;
using System.Data.SQLite;
public class Class1 : IDisposable
{
private readonly SQLiteCommand updateCookie = new SQLiteCommand("UPDATE moz_cookies SET value = @value, expiry = @expiry, isSecure = @isSecure, isHttpOnly = @isHttpOnly WHERE name = @name AND host = @host AND path = @path");
public Class1()
{
this.updateCookie.Parameters.AddRange(new[]
{
new SQLiteParameter("@name"),
new SQLiteParameter("@value"),
new SQLiteParameter("@host"),
new SQLiteParameter("@path"),
new SQLiteParameter("@expiry"),
new SQLiteParameter("@isSecure"),
new SQLiteParameter("@isHttpOnly")
});
}
private static void BindDbCommandToMozillaCookie(DbCommand command, Cookie cookie)
{
long expiresSeconds = (long)cookie.Expires.TotalSeconds;
command.Parameters["@name"].Value = cookie.Name;
command.Parameters["@value"].Value = cookie.Value;
command.Parameters["@host"].Value = cookie.Domain;
command.Parameters["@path"].Value = cookie.Path;
command.Parameters["@expiry"].Value = expiresSeconds;
command.Parameters["@isSecure"].Value = cookie.Secure;
command.Parameters["@isHttpOnly"].Value = cookie.HttpOnly;
}
public void WriteCurrentCookiesToMozillaBasedBrowserSqlite(string databaseFilename)
{
using (SQLiteConnection connection = new SQLiteConnection("Data Source=" + databaseFilename))
{
connection.Open();
using (SQLiteTransaction transaction = connection.BeginTransaction())
{
this.updateCookie.Connection = connection;
this.updateCookie.Transaction = transaction;
foreach (Cookie cookie in SomeOtherClass.GetCookieArray())
{
Class1.BindDbCommandToMozillaCookie(this.updateCookie, cookie);
this.updateCookie.ExecuteNonQuery();
}
transaction.Commit();
}
}
}
#region IDisposable implementation
protected virtual void Dispose(bool disposing)
{
if (!this.disposed && disposing)
{
this.updateCookie.Dispose();
}
this.disposed = true;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
~Class1()
{
this.Dispose(false);
}
private bool disposed;
#endregion
}
答案 0 :(得分:2)
没有一种“正确的方法”来处理数据库对象的生命周期。这完全取决于您的应用需求。
我个人的偏好是让代码尽可能简单。我倾向于根据需要重新创建Command和Parameter对象。这使我的功能尽可能自包含。它大大简化了我必须做的任何重新分解。
如果您担心重新创建对象的性能损失,您应该加载一个分析器并查看瓶颈的位置。在我构建的应用程序中,我发现创建DbCommand对象所花费的时间与执行查询所花费的时间相比是无关紧要的,因为它并没有真正影响我的应用程序性能。
答案 1 :(得分:2)
Domenic, 处置SQLiteCommand只是通知其活动读取器处理它的读取器并将参数和连接引用设置为null。
只要您正确处理已执行的阅读器并关闭/处置连接,您就不会因为缓存命令而面临资源泄漏的风险。
因此,重用缓存命令并简单地为参数赋值是迄今为止最有效的实现。
.Prepare()是SQLiteCommand中的noop
所以没有任何好处。
答案 2 :(得分:0)
我已经找到了sqlserver,如果我们重用具有相同连接的命令,它会更快。我计划测试不同的连接和交易,但它们看起来更快。