أفضل الممارسات إعادة تقاسم IDbConnection أو اتصال سلسلة / مصنع في التعليمات البرمجية الخاصة بك صافي

StackOverflow https://stackoverflow.com/questions/414207

سؤال

وأنا أتساءل ما يمكن أن يكون أفضل prectice بشأن الاتصالات mainataining إلى قاعدة البيانات في تطبيق صافي (ADO.NET ولكن أعتقد أن هذه الممارسة يجب أن تكون هي نفسها لأي طبقة البيانات). يجب أن إنشاء اتصال قاعدة البيانات ونشر ذلك في جميع أنحاء طلبي، أو سيكون من الأفضل أن يمر اتصال سلاسل / المصانع وإنشاء اتصال مخصصة، عند الحاجة إليها.

وكما فهمت برفومنس ضرب ليست ذات معنوية حقيقية مع تجميع وأنه يتيح لي للتعافي من الاتصالات كسر بسهولة جدا (سيتم إنشاء مجرد اتصال جديد) ولكن بعد ذلك مرة أخرى كائن اتصال غير لطيفة، نسبيا التجريد رفيعة المستوى، وخلق اتصال جديد لكل عملية (القيادة لا SQL، ولكن عملية التطبيق) يولد إضافية، رمز تكرار وكأنه مضيعة للوقت / الموارد (؟).

ما رأيك في هذه الحالات 2، ما هي من سلبيات / إيجابيات والنهج الذي تستخدمه في تطبيقات من واقع الحياة الخاصة بك؟

والشكر

هل كانت مفيدة؟

المحلول

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

إذا كان كل كائن الأعمال لخلق SQLConnection الخاصة به إلى قاعدة البيانات، فإن الصفقة تتصاعد إلى معاملة موزعة وكنت أرغب في تجنب ذلك.

ولم يعجبني الحاجة إلى تمرير الكائن SqlConnection كمعلمة لحفظ كائن، لذلك أنا خلقت ConnectionManager الذي يعالج خلق كائن SqlConnection بالنسبة لي، وتتبع استخدام الكائن SqlConnection، وفصل الكائن SqlConnection عندما لا في الاستخدام.

وهنا بعض التعليمات البرمجية كمثال للConnectionManager:

public class ConnectionManager: IDisposable
{
    private ConnectionManager instance;

    [ThreadStatic]
    private static object lockObject; 
    private static Object LockObject
    {
        get
        {
            if (lockObject == null)
                lockObject = new object();
            return lockObject;
        }
    }

    [ThreadStatic]
    private static Dictionary<string, ConnectionManager> managers;
    private static Dictionary<string, ConnectionManager> Managers
    {
        get
        {
            if (managers == null)
                managers = new Dictionary<string, ConnectionManager>();
            return managers;
        }
    }

    private SqlConnection connection = null;
    private int referenceCount;
    private string name;


    public static ConnectionManager GetManager(string connectionName)
    {
        lock (LockObject)
        {
            ConnectionManager mgr;
            if (Managers.ContainsKey(connectionName))
            {
                mgr = Managers[connectionName];
            }
            else
            {
                mgr = new ConnectionManager(connectionName);
                Managers.Add(connectionName, mgr);
            }

            mgr.AddRef();
            return mgr;
        }
    }

    private ConnectionManager(string connectionName)
    {
        name = connectionName;
        connection = new SqlConnection(GetConnectionString(connectionName));
        connection.Open();
    }

    private string GetConnectionString(string connectionName)
    {
        string conString = Configuration.ConnectionString;
        return conString; 
    }

    public SqlConnection Connection
    {
        get { return connection; }
    }

    private void AddRef()
    {
        referenceCount += 1;
    }

    private void DeRef()
    {
        lock (LockObject)
        {
            referenceCount -= 1;
            if (referenceCount == 0)
            {
                connection.Dispose();
                Managers.Remove(name);
            }
        }
    }

#region IDisposable Members

    public void Dispose()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            DeRef();
        }
    }

    ~ConnectionManager()
    {
        Dispose(false);
    }

#endregion

}

وهنا هو كيف لي أن استخدامها من كائن الأعمال:

public void Save()
{   
    using (ConnectionManager mrg = ConnectionManager.GetManager("SQLConnectionString")
    {
        using (SQLCommand cmd = new SQLCommand)
        {
            cmd.connection = mgr.Connection
            // More ADO Code Here
        }

        _childObject.Save(); //this child object follows the same pattern with a using ConnectionManager.
    }
}

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

وهذا هو نمط تعلمت من روكي Lhotka في إطار CSLA له.

وكيث

نصائح أخرى

وأنت حقا لا ينبغي أن يكون التعامل مع هذه المشكلة بنفسك، كما أن هناك عدد لا يحصى من الأدوات هناك التي يمكن أن نفعل ذلك لك.

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

إذا تقرر السماح مكونات مفتوحة مباشرة اتصالات ديسيبل ثم فمن المرجح أن دورة حياة اتصال سوف يكون ايضا غرامة الحبيبات ويؤدي في كثير من الاتصالات المفتوحة / مغلق للعملية مستخدم واحد.

ومزود ADO.NET SQL Server لا اتصال تجميع نفسها. يمكنك التحكم في حجم تجمع بواسطة MinPoolSize وMaxPoolSize في سلسلة الاتصال.

وشيء واحد أن نكون حذرين من في المثال الخاص بك هو أن تطبيقات ASP.NET يجب عدم استخدام التخزين ThreadStatic، باعتباره موضوع يمكن إعادة استخدامها، وإذا لم يكن لتنظيف جميع الأشياء الخاصة بك كنت في نهاية المطاف مع شنقا اتصال حولها.

في التطبيق ASP.NET فما استقاموا لكم فاستقيموا استخدام مجموعة HttpContext.Items بدلا من ذلك. كنت تنفيذ IDisposable، ولكن رأيت سيناريوهات حيث ننسى المشروعات الإنمائية للاتصال تخلص أو ضع التعليمات البرمجية في كتلة باستخدام.

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