EF6 Create Different DataContext on runtime(运行时改变连接字符串)

引言

 

在使用EF时,有时我们需要在程序运行过程中动态更改EF的连接字符串,但不幸的时EF是否对

ConfigurationManager.RefreshSection("xxx")

这行代码的影响不大,我没去深究,还请大侠指点。(本人猜测,EF内部实现没有订阅RefreshSection的事件去做相应的更换连接字符串的处理),如果确实想用该方法通过修改配置文件来实现动态更换连接字符串,那最保守的做法再加上个重启应用程序的方法。(确保EF能重新读到新的配置信息。)

 

这个时候就需要我们在DataContext新建时使用指定DBConnection来解决该问题,Demo如下:

 

APP.CONFIG (Uses EF 6)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters>
<parameter value="Data Source=localhost; Integrated Security=True; MultipleActiveResultSets=True" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
</configuration>

the code to make as small as possible for Demo:

using System;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Migrations; namespace Ef6Test {
public class Program {
public static void Main(string[] args) {
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Ef6Ctx, Ef6MigConf>());
WhichDb.DbName = "HACKDB1";
var sqlConn = GetSqlConn4DBName(WhichDb.DbName);
var context = new Ef6Ctx(sqlConn);
context.Database.Initialize(true);
AddJunk(context);
//sqlConn.Close(); //?? whatever other considerations, dispose of context etc... Database.SetInitializer(new MigrateDatabaseToLatestVersion<Ef6Ctx, Ef6MigConf>()); // yes its default again reset this !!!!
WhichDb.DbName = "HACKDB2";
var sqlConn2 = GetSqlConn4DBName(WhichDb.DbName);
var context2 = new Ef6Ctx(sqlConn2);
context2.Database.Initialize(true);
AddJunk(context2);
}
public static class WhichDb { // used during migration to know which connection to build
public static string DbName { get; set; }
}
private static void AddJunk(DbContext context) {
var poco = new pocotest();
poco.f1 = DateTime.Now.ToString();
// poco.f2 = "Did somebody step on a duck?"; //comment in for second run
context.Set<pocotest>().Add(poco);
context.SaveChanges();
}
public static DbConnection GetSqlConn4DBName(string dbName) {
var sqlConnFact =
new SqlConnectionFactory(
"Data Source=localhost; Integrated Security=True; MultipleActiveResultSets=True");
var sqlConn = sqlConnFact.CreateConnection(dbName);
return sqlConn;
}
}
public class MigrationsContextFactory : IDbContextFactory<Ef6Ctx> {
public Ef6Ctx Create() {
var sqlConn = Program.GetSqlConn4DBName(Program.WhichDb.DbName); // NASTY but it works
return new Ef6Ctx(sqlConn);
}
}
public class Ef6MigConf : DbMigrationsConfiguration<Ef6Ctx> {
public Ef6MigConf() {
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
}
public class pocotest {
public int Id { get; set; }
public string f1 { get; set; }
// public string f2 { get; set; } // comment in for second run
}
public class Ef6Ctx : DbContext {
public DbSet<pocotest> poco1s { get; set; }
public Ef6Ctx(DbConnection dbConn) : base(dbConn, true) { }
}
}

 

 

参考

https://*.com/questions/18272708/how-to-force-dbcontext-refresh-connection-string-from-config

 

https://*.com/questions/15504465/entityframework-code-first-custom-connection-string-and-migrations/16133150#16133150

 

https://github.com/mono/entityframework/blob/master/src/EntityFramework/Infrastructure/SqlConnectionFactory.cs

上一篇:一些peoplecode小技巧【一】


下一篇:手机APP中使用history.back()返回没有效果的解决