سؤال

ما يبدو لي اختيارات:

  1. جعل صففي الفوري IDisposable. وبعد إنشاء بلدي DbCommand مثيلات private readonly الحقول، وفي المنشئ، أضف المعلمات التي يستخدمونها. كلما أردت أن أكتب إلى قاعدة البيانات، اربط هذه المعلمات (أعد استخدام نفس مثيلات الأمر)، واضبط Connection و Transaction خصائص، ثم اتصل 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
}
هل كانت مفيدة؟

المحلول

بالولايات المتحدة، والتخلص من SQLITECommand تشير ببساطة إلى قارئها النشط للتخلص من قارئها وتعيين المعلمات ومرجع الاتصال إلى NULL.

أنت لست في خطر تسرب الموارد من خلال التخزين المؤقت أمرا طالما كنت تتخلص بشكل صحيح من القارئ المنفذ وإغلاق / التخلص من الاتصال.

لذا، فإن إعادة استخدام أمر مخزير مؤقتا ومجرد تعيين القيم إلى المعلمات هو الأكثر كفاءة.

prepare () هو noop في SQLITECommand لذلك لا توجد فائدة موجودة هناك.

نصائح أخرى

لا توجد "طريقة صحيحة" واحدة للتعامل مع دورة حياة كائن قاعدة البيانات الخاصة بك. كل شيء يعتمد على احتياجات طلبك.

تفضيلي الشخصي هو الحفاظ على الكود بسيطة قدر الإمكان. أميل إلى إعادة إنشاء كائنات القيادة والمعلمة حسب الحاجة. هذا يتيح لوظيفاتي أن تكون ذاتية تحتوي على قدر الإمكان. لقد تبسيط ذلك إلى حد كبير أي عامل يعاني من القيام به.

إذا كنت تشعر بالقلق إزاء ضرب الأداء من كائنات إعادة إنشائه، يجب عليك تحميل ملف تعريف ومشاهدة أين تكون رقاب زجاجة. في التطبيقات التي قمت ببناءها، لقد وجدت الوقت الذي يقضيه في إنشاء كائنات DBCommand غير ملموسة للغاية مقارنة بالوقت الذي يقضيه في تنفيذه الاستعلام أنه لا يعمل حقا في أداء تطبيقاتي.

لقد وجدت مع SQLServer إذا أعاد استخدام الأمر بنفس الاتصال، أسرع بكثير. أخطط لاختبار اتصالات مختلفة ومعاملات ولكن يبدو أنها أسرع.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top