1

我似乎有两个选择:

  1. 让我的班级实现IDisposable。将我的DbCommand实例创建为private readonly字段,并在构造函数中添加它们使用的参数。每当我想写入数据库时​​,绑定到这些参数(重用相同的命令实例),设置ConnectionandTransaction属性,然后调用ExecuteNonQuery. 在该Dispose方法中,调用Dispose这些字段中的每一个。
  2. 每次我想写入数据库时​​,写using(var cmd = new DbCommand("...", connection, transaction))一下命令的用法,并在每次调用之前添加参数并绑定到它们ExecuteNonQuery。我假设我不需要每个查询的新命令,每次打开数据库时都需要一个新命令(对吗?)。

这两者似乎都有些不雅,而且可能不正确。

对于#1,我的用户很烦我这个类现在IDisposable只是因为我使用了几个DbCommands (这应该是他们不关心的实现细节)。我也有点怀疑保留一个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
}
4

3 回答 3

2

没有单一的“正确方法”来处理您的数据库对象生命周期。这完全取决于您的应用程序需求。

我个人的偏好是使代码尽可能简单。我倾向于根据需要重新创建命令和参数对象。这让我的功能尽可能自包含。它大大简化了我必须做的任何重构。

如果您担心重新创建对象的性能影响,您应该加载一个分析器并查看您的瓶颈在哪里。在我构建的应用程序中,我发现创建 DbCommand 对象所花费的时间与执行查询所花费的时间相比微不足道,以至于它并没有真正影响我的应用程序性能。

于 2009-08-11T20:12:16.303 回答
2

Domenic, Disposing a SQLiteCommand 只是简单地向它的活动阅读器发出信号以释放它的阅读器,并将参数和连接引用设置为 null。

只要您正确处置已执行的阅读器并关闭/处置连接,就不会因缓存命令而面临资源泄漏的风险。

因此,重用缓存的命令并简单地为参数分配值是迄今为止最有效的实现。

.Prepare() 是noopSQLiteCommand 中的一个,因此在那里没有任何好处。

于 2010-04-25T18:31:26.703 回答
0

如果我们使用相同的连接重用命令,我发现使用 sqlserver 会更快。我计划测试不同的连接和事务,但它们似乎更快。

于 2009-11-02T20:24:27.550 回答