Есть база данных, созданная на основе CodeFirst EntityFramework.
Я создал класс для сохранения данных Connection String'a и методы сохранения и выгрузки данных
public class ConnectionString
{
public string DataSource { get; set; }
public string InitialCatalog { get; set; }
public string UserId { get; set; }
public string Password { get; set; }
public ConnectionString() { }
public ConnectionString(string dataSource, string initialCatalog, string userId, string password)
{
DataSource = dataSource;
InitialCatalog = initialCatalog;
UserId = userId;
Password = password;
}
public override string ToString()
{
return $"Data Source={DataSource};Initial Catalog={InitialCatalog};User Id={UserId};Password={Password}";
}
public ConnectionString LoadFile(string path)
{
try
{
ConnectionString result;
XmlSerializer formatter = new XmlSerializer(typeof(ConnectionString));
using (var fs = new FileStream("DataConnection.xml", FileMode.Open))
{
result = (ConnectionString)formatter.Deserialize(fs);
}
return result;
}
catch
{
throw new Exception("File not uploaded!");
}
}
public void SaveFile(object obj, string path)
{
try
{
XmlSerializer formatter = new XmlSerializer(obj.GetType());
using (var fs = new FileStream("DataConnection.xml", FileMode.OpenOrCreate))
{
formatter.Serialize(fs, obj);
}
}
catch
{
throw new Exception("File not saved!");
}
}
}
Есть класс представляющий таблицу в базе данных
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public int Age { get; set; }
}
И класс принимающий DbContext
public class UserContext : DbContext
{
ConnectionString cs;
public UserContext() : base("DbConnection")
{ }
public UserContext(string connect) : base(connect)
{
try
{
cs = new ConnectionString();
var loadData = cs.LoadFile("DataConnection.xml");
string connString = String.Format("Data Source={0};Initial Catalog={1};User Id={2};Password={3}", loadData.DataSource, loadData.InitialCatalog, loadData.UserId, loadData.Password);
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
MessageBox.Show("Connect!");
}
}
catch
{
MessageBox.Show("No connection!");
}
}
public DbSet<User> Users { get; set; }
}
Так заполнял данными когда изначально создал код и базу данных
public void CreateData()
{
using (db = new UserContext())
{
User user1 = new User { FirstName = "Eugene", Age = 28 };
User user2 = new User { FirstName = "Serhiy", Age = 32 };
db.Users.Add(user1);
db.Users.Add(user2);
db.SaveChanges();
}
}
Вопрос вот в чем, если я захочу поменять базу данных, пересоздам файл с нужным подключением. Как мне с файла правильно вытянуть эту строку и передать в DbContext?
В качестве просто идеи, как это можно реализовать.
Например, у нас есть контекст (просто его эмуляция для примера)
public class DbContext : IDisposable
{
public void Dispose() {}
public DbContext(string str)
{
Console.WriteLine($"dc is using {str}");
}
}
Я накидал нехитрый класс для хранния конфига
public class ConnectionStringSource
{
private string _filename;
private Dictionary<string,string> _conStrings = new Dictionary<string,string>();
private string _selected;
public ConnectionStringSource(string filename) =>
_filename = filename;
public void Load()
{
using(var sr = new StreamReader(_filename))
{
var ser = new XmlSerializer(typeof(ConnectionStringSourceSettings));
var settings = (ConnectionStringSourceSettings)ser.Deserialize(sr);
_conStrings = settings.ConnectionStrings.ToDictionary(x=>x.name, x=>x.connString);
_selected = settings.Selected;
}
}
public void Save()
{
using (var sw = new StreamWriter(_filename))
{
var ser = new XmlSerializer(typeof(ConnectionStringSourceSettings));
var settings = new ConnectionStringSourceSettings()
{
ConnectionStrings = _conStrings.Select(x =>(name : x.Key, connString:x.Value)).ToList(),
Selected = _selected
};
ser.Serialize(sw, settings);
}
}
public void Add(string name, string connectionString)=>
_conStrings[name] = connectionString;
public void SetActive(string name){
if (_conStrings.ContainsKey(name))
_selected = name;
else throw new ArgumentException(nameof(name));
}
public string GetSelectedConnectionString() =>
_conStrings[_selected];
public class ConnectionStringSourceSettings
{
public List<(string name, string connString)> ConnectionStrings { get; set; } = new List<(string, string)>();
public string Selected { get; set; }
}
}
Тогда мы можем в реальном времени кидать в конфиг новые строки, созранять его, загружать его, и т.д.
var source = new ConnectionStringSource(@"D:\temp\SampleConfig.xml");
source.Add("string1", "my_connection_string");
source.SetActive("string1");
using(var dc = new DbContext(source.GetSelectedConnectionString()))
{
// .....
}
source.Add("string2", "my_connection_string_2");
source.SetActive("string2");
using (var dc = new DbContext(source.GetSelectedConnectionString()))
{
// .....
}
source.SetActive("string1");
using (var dc = new DbContext(source.GetSelectedConnectionString()))
{
// .....
}
source.Save();
В выводе увидим, что в разное время контексты данных будут получать разные строки
dc is using my_connection_string
dc is using my_connection_string_2
dc is using my_connection_string
При этом контексту самому абсолютно не интересно, как там для него выбирается строка соединения.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
У меня есть виджет в EditorWindow который формирует список префабов:
Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском