【问题标题】:How to change database name in dbcontext connection string at runtime如何在运行时更改 dbcontext 连接字符串中的数据库名称
【发布时间】:2017-07-26 01:09:32
【问题描述】:

我的 Asp.Net MVC 应用程序设置如下。 解决方案中有 4 个项目。

  • ge.Web
  • ge.BLL
  • ge.Core
  • ge.Entities

控制器在 ge.Web 中初始化 ge.Core 中的存储库对象

 public class MapsController : Controller
 {
      private AssessmentRepository repAssessments = new AssessmentRepository("name=GEContext", schoolCode);

      public ActionResult DisplaySearchResults()
      {
        .....
      }
  }

评估存储库

  public class AssessmentRepository : Repository<Assessment>, IAssessmentRepository
{
    public AssessmentRepository(string connString, string schoolCode)
        :base(connString, schoolCode)
    { }
 }

存储库

  public class Repository<TEntity> : IRepository<TEntity> where TEntity:class
{
    protected readonly GEContext context;


    public Repository(string connString, string schoolCode) {
        context = new GEContext(connString);
    }
 }

GEContext

 public class GEContext : DbContext
 {
    public GEContext(string connString):base(connString) 
    {
        this.Configuration.LazyLoadingEnabled = false;
        Database.SetInitializer(new MySqlInitializer());
    }
  }

DbContext

public class DbContext : IDisposable, IObjectContextAdapter
{
    public DbContext(string nameOrConnectionString);
}

Web.Config

 <add name="GEContext" connectionString="server=localhost;port=4040;uid=root;pwd=xxx;database=ge" providerName="MySql.Data.MySqlClient" />

现在我想用 database=ge_[schoolCode] 替换 web.config 中的“database=ge”。在运行时我该怎么做?

更新 我的解决方案不起作用。所以我再次说明问题。

Web.Config

我已将我的配置文件更改为以下内容(以前 GEContext 是唯一的连接字符串)

<connectionStrings>
<add name="GEContext_sc001" connectionString="server=localhost;port=4040;uid=root;pwd=blabla;database=db_sc001" providerName="MySql.Data.MySqlClient" />
<add name="GEContext_sc002" connectionString="server=localhost;port=4040;uid=root;pwd=blabla;database=db" providerName="MySql.Data.MySqlClient" />

<appSettings>
     <add key="SchoolCodes" value="sc001,sc002"/>

这些是允许的学校代码

现在,当用户在登录屏幕输入学校代码时,系统会根据 SchoolCodes 键中的代码对其进行验证。如果是,那么它应该尝试连接到该特定连接的 connectionString。现在当我的代码来了

UserManager.FindAsync

在 AccountController 的登录功能中,它试图找到 GEContext 时崩溃。那个套装在哪里?我该如何改变它?

我已将控制器中的存储库调用更改如下

private static string schoolCode = (string)System.Web.HttpContext.Current.Session["SchoolCode"];

    private AssessmentRepository repAssessments = new AssessmentRepository("name=GEContext_" + schoolCode);

UPDATE-2 以下出现在 ge.Web

IdentityConfig.cs

  public class ApplicationUserManager : UserManager<ApplicationUser, int>
{
    public ApplicationUserManager(IUserStore<ApplicationUser, int> store)
        : base(store)
    {
    }

     public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) 
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser, Role, int, UserLogin, UserRole, UserClaim>(context.Get<ApplicationDbContext>()));
  ...........
 }

ge.Core 中存在以下内容

ApplicationDbContext

 public class ApplicationDbContext : IdentityDbContext<ApplicationUser, Role, int, UserLogin, UserRole, UserClaim>
{

     public ApplicationDbContext(string connString)
        : base(connString)
    {
        Database.SetInitializer(new MySqlInitializer());
    }

    public static ApplicationDbContext Create()
    {

        return new ApplicationDbContext("name=GEContext_");
    }
}

我如何将 schoolCode 从 ge.web 传递到 ge.Core(答案应该是直截了当的,但目前我无法理解)

UPDATE-3

正如 itikhomi 所说并得到 this post 的帮助,我已将代码更改如下

  1. 在 ApplicationDbContext 类中添加了以下内容

    公共静态 ApplicationDbContext 创建(字符串 scCode){ return new ApplicationDbContext("name=GEContext_" + scCode); }

  2. 在 AccountController 中登录

    var appDbContext = ApplicationDbContext.Create(model.SchoolCode);

                Request.GetOwinContext().Set<ApplicationDbContext>(appDbContext);
    

它仍然没有找到正确的数据库

【问题讨论】:

  • 您只需更改 web.config。您还可以添加多个连接字符串值“GEContext”、“GEContext2”、“GEContext3”,然后让您的程序动态选择这些连接之一。
  • 我的数据库名称将是 db_[schoolCode]..所以我基本上需要验证登录时输入的学校代码。我尝试通过在连接字符串中重命名数据库名称来连接输入的学校代码
  • 您要问的内容非常广泛。这里有一些指导 stackoverflow.com/questions/35956345/…benfoster.io/blog/…

标签: asp.net-mvc entity-framework


【解决方案1】:

你有两种方法

1)

    using System.Data.SqlClient;

         public class Repository<TEntity> : IRepository<TEntity> where TEntity:class
        {
            protected readonly GEContext context;


            public Repository(string connString, string schoolCode) {
                context = new GEContext(connString);
                var connection = new SqlConnectionStringBuilder(context.Database.Connection.ConnectionString);
                connection.InitialCatalog = "YOUR_PREFIX_FROMSOMEWHERE"+schoolCode;
                context.Database.Connection.ConnectionString = connection.ConnectionString;
            }
         }

2)如果您想在使用前打开连接时切换ChangeDatabase

//open connection if it close
    context.Database.Connection.ChangeDatabase("DATABASE-NAME");

注意:如果使用 ChangeDatabase 连接应该已经打开

更新3:

你需要做一些这样的思考:

 public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext()
            : base("DefaultConnection", throwIfV1Schema: false)
        {

        }

        public ApplicationDbContext(string schoolCode)
            : base(schoolCode)
        {
            var connection = new SqlConnectionStringBuilder(this.Database.Connection.ConnectionString);
            connection.InitialCatalog = "YOUR_PREFIX_FROMSOMEWHERE" + schoolCode;
            this.Database.Connection.ConnectionString = connection.ConnectionString;
        }

        public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext();
        }
    }

在帐户控制器中:

public ApplicationSignInManager SignInManager
        {
            get
            {

                if (_signInManager == null)
                {
                    var code = HttpContext.Request.Form.Get("SchoolCode");//Get from FORM\QueryString\Session whatever you wants
                    if (code != null)
                    {
                        HttpContext.GetOwinContext().Set<ApplicationSignInManager>(new ApplicationSignInManager(_userManager, HttpContext.GetOwinContext().Authentication));
                    }
                    _signInManager = HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
                }

                return _signInManager;
            }
            private set
            {
                _signInManager = value;
            }
        }

 public ApplicationUserManager UserManager
        {
            get
            {
                if (_userManager == null)
                {
                    var code = HttpContext.Request.Form.Get("SchoolCode");//Get from FORM\QueryString\Session whatever you wants
                    if (code != null)
                    {
                        var appDbContext = new ApplicationDbContext(code);

                        HttpContext.GetOwinContext().Set<ApplicationDbContext>(appDbContext);
                        HttpContext.GetOwinContext().Set<ApplicationUserManager>(new ApplicationUserManager(new UserStore<ApplicationUser>(appDbContext))); //OR USE your specified create Method
                    }
                    _userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
                }
                return _userManager;
            }
            private set
            {
                _userManager = value;
            }
        }

您的问题是在您更改 OWIN 上下文之前创建了 UserManager 的 Store,在这种情况下,最好使用像 here 这样的 DI

【讨论】:

  • 谢谢..我已经编辑了我的应用程序,你能检查一下上面的更新吗?
  • @Samra,尝试调试并在 AccountController 中为我提供 schoolCode 值,我认为它将为空,这就是您收到错误的原因
  • 问题不在于它存在的学校代码,而是当它进入 accountController 中的登录功能但在 var user = await UserManager.FindAsync(model.Username, model.Password);
  • 这里正在寻找GEContext
  • @Samra,请提供身份配置,有手动设置你的旧GEContext,或者搜索“GEContext”找到它
【解决方案2】:

您可以为打开的连接更改数据库

context.Database.GetDbConnection().ChangeDatabase("");

【讨论】:

    【解决方案3】:

    我在 itikhomi 的帮助下解决了这个问题..发布最终代码..

    ApplicationDbContext

    public static ApplicationDbContext Create()
        {
            return new ApplicationDbContext("name=GEContext");
        }
    

    帐户控制器

     public ApplicationUserManager UserManager {
            get
            {
                if (System.Web.HttpContext.Current.Session["SchoolCode"] == null)
                    return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
                else
                {
                    var appDbContext = ApplicationDbContext.Create(System.Web.HttpContext.Current.Session["SchoolCode"].ToString());//new ApplicationDbContext("name=GEContext", System.Web.HttpContext.Current.Session["SchoolCode"].ToString());
    
                    HttpContext.GetOwinContext().Set<ApplicationDbContext>(appDbContext);
                    HttpContext.GetOwinContext().Set<ApplicationUserManager>(new ApplicationUserManager(new UserStore<ApplicationUser, Role, int, UserLogin, UserRole, UserClaim>(appDbContext)));
    
                    return HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
                }
            }
            private set
            {
                _userManager = value;
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2018-05-20
      • 2021-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-17
      相关资源
      最近更新 更多