entity framework:在运行时更改连接字符串

假设有一个ASP.NET MVC应用程序使用Entity Framework 6,代码优先方法和StructureMap作为IoC。
它还使用工作单元模式。 以下是代码:

域类

public class Product     {         public int Id { get; set; }         public string Name { get; set; }         public decimal Price { get; set; }            } 

IUnitOfWork和DbContext:

  public interface IUnitOfWork { IDbSet Set() where TEntity : class; int SaveChanges(); } public class Sample07Context : DbContext, IUnitOfWork { public DbSet Products { set; get; } #region IUnitOfWork Members public new IDbSet Set() where TEntity : class { return base.Set(); } #endregion } 

服务类中的业务逻辑:

  public interface IProductService { void AddNewProduct(Product product); IList GetAllProducts(); }    public class ProductService : IProductService    {        IUnitOfWork _uow;        IDbSet _products;        public ProductService(IUnitOfWork uow)        {            _uow = uow;            _products = _uow.Set();        }        public void AddNewProduct(Product product)        {            _products.Add(product);        }        public IList GetAllProducts()        {            return _products.Include(x => x.Category).ToList();        }    } 

在控制器中注入服务类

  public class HomeController : Controller { private IProductService _productService; private IUnitOfWork _uow; public HomeController(IUnitOfWork uow, IProductService productService) { _productService = productService; _uow = uow; } [HttpGet] public ActionResult Index() { var list = _productService.GetAllProducts(); return View(list); } } 

我们在app_start中调用的StructureMap配置:

  private static void initStructureMap() { ObjectFactory.Initialize(x => { x.For().HttpContextScoped().Use(() => new Sample07Context()); x.ForRequestedType().TheDefaultIsConcreteType(); }); //Set current Controller factory as StructureMapControllerFactory ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); } 

单个数据库一切正常,但在我的场景中,用户可以使用多个数据库,我的意思是用户应该能够在运行时更改连接字符串。 我们为用户在应用程序中创建的每个项目创建单独的数据库。
现在问题是我们将DbContext注入服务并且DbContext从web.config读取连接字符串,因此当用户更改数据库时,我们无法将新连接字符串设置为DbContext。
你有什么建议?

根据我的经验,我在EF 6中使用了Database First模式。当我添加Entity Data Model时, DbContext将如下生成。

 public TestEntities() : base("name=TestEntities") { } 

TestEntities表示TestEntitiesConnectionString元素

    

但您可以将默认代码更改为以下。

 public partial class TestEntities : DbContext { public TestEntities() : base("name=TestEntities") { } public TestEntities(string sConnectionString) : base(sConnectionString) { } ...} 

所以你有两个选择来获得数据库连接。

  1. 使用默认值。 EF将在配置文件中找到连接字符串。

  2. 将连接字符串传递给DbContext。

代码如下所示。

 EntityConnection entityConn =DBConnectionHelper.BuildConnection(); using (var db = new TestEntities(entityConn.ConnectionString)) { .... } 

至于How to build a EntityConnection?的问题How to build a EntityConnection? 。 请参阅MSDN EntityConnection 。

希望它有所帮助。

谢谢。

默认情况下,在Entity Framework中使用的连接字符串的名称是从您的DbContext类的名称推断出来的。 但是,您可以将连接字符串作为构造函数参数传递:

 public class MyDbContext : DbContext, IUnitOfWork { public MyDbContext(string connectionString) : base(connectionString) { } } 

然后,您可以配置StructureMap以传入当前连接字符串,例如

 For().Use(ctx => new MyDbContext(TheConnectionStringToUse)); 

这可能来自您在代码中设置的静态值,当前会话等。

我将建议一条完全不同的道路。 假设您在web.config中设置了连接字符串,您说你为什么不使用web.debug.config和web.release.config transforrms来适当地设置连接字符串?

即在web.debug.config中

    

和web.release.config这样

    

这里有一个非常详尽的解释

  public partial class YourDBContextClass { // Add a constructor to allow the connection string name to be changed public YourDBContextClass(string connectionStringNameInConfig) : base("name=" + connectionStringNameInConfig) { } } 

将多个连接字符串添加到web或app.config文件中。

在你的程序代码中:

 YourDBContextClass dbcontext = new YourDBContextClass("alternateconnectionstringname"); 

这两种方法适用于两种不同的情况:

  • 该转换适用于部署仅针对不同环境(测试,生产)进行更改的连接字符串。

  • 在单独的文件中添加构造函数(采用连接字符串名称)以扩展部分dbcontext类的方法允许在运行时切换连接。

使用不同的名称在App.Config文件中添加两个不同的连接字符串。

使用重载在实体构造函数中设置当前连接字符串名称。

在代码文件中

 public ASM_DBEntities() : base("name=ASM_DBEntities") { } public ASM_DBEntities(string conn) : base("name=ASM_DBEntities1") { } 

当我们用对象传递字符串然后使用不同的连接字符串。