.net - 我应该在哪里创建我的 DbCommand 实例?

标签 .net sqlite ado.net system.data.sqlite system.data

我似乎有两个选择:

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

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

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

    最佳答案

    多米尼克,
    处理 SQLiteCommand 只是简单地向其事件阅读器发出信号以处理其阅读器并将参数和连接引用设置为 null。

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

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

    .Prepare() 是 noop在 SQLiteCommand 中,所以那里没有任何好处。

    关于.net - 我应该在哪里创建我的 DbCommand 实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1252039/

    相关文章:

    .net - 数据集与数据库

    c# - 将大量项目添加到 ListView

    c# - 内存消耗管理策略

    c++ - 将 MySQL 表存储到文件(sqlite?)

    c# - 用数据读取器填充业务对象的最快方法?

    linq - 与 Ado .net、 Entity Framework 、LINQ 混淆

    c# - 如何观察DbSet<T>的Add Action ?

    Android SQLite long 值被检索/转换为 int 值

    java - 值没有插入到 SQLite 数据库

    c# - 如何从数据集中检索特定列?