كيف أقوم بتعيين تكوين سلسلة الاتصال برمجياً في .net؟

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

سؤال

أرغب في تعيين سلسلة اتصال برمجيًا، دون أي تغيير على الإطلاق في أي ملفات تكوين/مفاتيح التسجيل.

لدي هذا الجزء من التعليمات البرمجية، ولكن لسوء الحظ فإنه يطرح استثناءً بـ "التكوين للقراءة فقط".

ConfigurationManager.ConnectionStrings.Clear();
string connectionString = "Server=myserver;Port=8080;Database=my_db;...";
ConnectionStringSettings connectionStringSettings = 
  new ConnectionStringSettings("MyConnectionStringKey", connectionString);
ConfigurationManager.ConnectionStrings.Add(connectionStringSettings);

يحرر:المشكلة هي أن لدي رمزًا موجودًا يقرأ سلسلة الاتصال من التكوين.لذا فإن تعيين سلسلة التكوين يدويًا، أو من خلال أحد الموارد، لا يبدو أنه خيارات صالحة.ما أحتاجه حقًا هو طريقة لتعديل التكوين برمجيًا.

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

المحلول

لقد كتبت عن هذا في انشر على مدونتي.الحيلة هي استخدام الانعكاس لإدخال القيم كوسيلة للوصول إلى الحقول (والطرق) غير العامة.

على سبيل المثال.

var settings = ConfigurationManager.ConnectionStrings[ 0 ];

var fi = typeof( ConfigurationElement ).GetField( "_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic );

fi.SetValue(settings, false);

settings.ConnectionString = "Data Source=Something";

نصائح أخرى

كنت أبحث عن إجابة لنفس السؤال حول السماح للمستخدم بتعديل سلسلة الاتصال بنقرة واحدة على التطبيق عن طريق تحديد خادم SQL محلي.

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

string NewConnection = "";
// get the user to supply connection details
frmSetSQLConnection frm = new frmSetSQLConnection();
frm.ShowDialog();
if (frm.DialogResult == DialogResult.OK)
{
    // here we set the users connection string for the database
    // Get the application configuration file.
    System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
    // Get the connection strings section.
    ConnectionStringsSection csSection = config.ConnectionStrings;
    foreach (ConnectionStringSettings connection3 in csSection.ConnectionStrings)
    {
        // Here we check for the preset string - this could be done by item no as well
        if (connection3.ConnectionString == "Data Source=SQL204\\SQL2008;Initial Catalog=Transition;Integrated Security=True")
        {
             // amend the details and save
             connection3.ConnectionString = frm.Connection;
             NewConnection = frm.Connection;
             break;
        }
    }
    config.Save(ConfigurationSaveMode.Modified);
    // reload the config file so the new values are available

    ConfigurationManager.RefreshSection(csSection.SectionInformation.Name);

    return clsDBMaintenance.UpdateDatabase(NewConnection))
}

هناك طريقة أخرى للتعامل مع هذا وهي العمل على المجموعة مباشرة:

var settings = ConfigurationManager.ConnectionStrings;
var element = typeof(ConfigurationElement).GetField("_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);
var collection = typeof(ConfigurationElementCollection).GetField("bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic);

element.SetValue(settings, false);
collection.SetValue(settings, false);

settings.Add(new ConnectionStringSettings("ConnectionStringName", connectionString));

// Repeat above line as necessary

collection.SetValue(settings, true);
element.SetValue(settings, true);

أجد أن هذا يناسبني:

Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
ConnectionStringsSection section = config.GetSection("connectionStrings") as         ConnectionStringsSection;
if (section != null)
{
    section.ConnectionStrings["MyConnectionString"].ConnectionString = connectionString;
    config.Save();
}

يؤدي هذا إلى الكتابة فوق سلسلة اتصال موجودة.

أستخدم حاليًا حقن التبعية للتعامل مع سلاسل الاتصال المختلفة في dev/prod vs.بيئات الاختبار.لا يزال يتعين علي تغيير تكوين الويب يدويًا إذا كنت أرغب في الانتقال بين dev وprod، ولكن للاختبار، لدي واجهة IConnectionStringFactory مع تطبيق افتراضي ينظر إلى تكوين الويب وتكوين اختبار بديل يُرجع قيمًا ثابتة.وبهذه الطريقة، عندما أقوم بالاختبار، أقوم ببساطة بتعيين المصنع على تنفيذ الاختبار وسيقوم بإرجاع سلسلة اتصال الاختبار للمفتاح الذي أطلبه.وإلا فإنه سوف ننظر في webconfig.

يمكنني توسيع هذا إلى تطبيق آخر لـ dev vs.prod ولكني أشعر براحة أكبر عند وجود تطبيق واحد لـ IConnectionStringFactory في مجموعة الإنتاج الخاصة بي وتنفيذ الاختبار في مجموعة الاختبار الخاصة بي.

يمكنك وضعه في ملف الموارد بدلا من ذلك.لن يحتوي على الميزات المضمنة لفئة ConfigurationManager، لكنه سيعمل.

بافتراض الموارد.resx:

Resources.Default.ConnectionString = "Server=myserver;" // etc

ثم في الكود الخاص بك:

conn.ConnectionString = Resources.Default.ConnectionString

إنه اختراق، وأنا أعلم.

بالإضافة إلى الإجابات الأخرى المقدمة، وبافتراض أن سلسلة الاتصال ليست مجرد متغير تكوين آخر أو ثابت ككل، قد تفكر في استخدام SqlConnectionStringBuilder class بدلاً من توصيل السلسلة معًا مباشرةً.

يحرر:Ups، آسف للتو رأيت أنك تريد قراءة سلسلة الاتصال الخاصة بك (كاملة على ما أعتقد) من مصدر آخر.

يبدو أن التسمية تم تغييرها اعتبارًا من .NET Core 2.1 ، يجب أن تعمل إجابة David Gardiner بهذه الطريقة للإشارة إلى الإصدارات الجديدة والقديمة:

إعدادات فار = ConfigurationManager.ConnectionStrings[ 0 ];

var fi = typeof( ConfigurationElement ).GetField( "_bReadOnly", BindingFlags.Instance | BindingFlags.NonPublic );

if(fi == null)
{
  fi = typeof(System.Configuration.ConfigurationElementCollection).GetField("_readOnly", BindingFlags.Instance | BindingFlags.NonPublic);
}

fi.SetValue(settings, false);

settings.ConnectionString = "Data Source=Something";

يتم استخدام مدير التكوين ل يقرأ من ملف التكوين.

الحل الخاص بك هو ببساطة تعيين conn.ConnectionString إلى سلسلة conn التي تحتاجها.

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