用户使用Unity容器登录后如何将连接字符串设置为DbContext?

时间:2014-12-09 23:49:39

标签: c# asp.net-mvc entity-framework connection-string unity-container

我正在构建一个连接到不同数据库的MVC应用程序,具体取决于已登录的用户。

为此,我有3个项目DAL使用实体框架(DataBaseFirst),其中我扩展了dbcontext,以便我可以像这样传递连接字符串:

  public partial class ARACultivoEntities
{
    public ARACultivoEntities(string nameOfConnectionString)
        : base(nameOfConnectionString)
    {
    }
}

注意:我在mvc项目的web.config中定义了连接字符串。

还有另一个项目,服务,我有一个genericService,其他服务可以从这里继承这个:

 public class GenericService<T> : IGenericService<T>
    where T : class
{

    protected ARACultivoEntities Db;


    protected DbSet<T> Table;



    public GenericService(string nameConnectionString)
    {
        if (string.IsNullOrEmpty(nameConnectionString))
        {
            throw new ArgumentNullException("nameConnectionString");
        }

        Db = new ARACultivoEntities(nameConnectionString);
        Table = Db.Set<T>();
    }

现在我在登录时在用户声明中保存连接字符串的名称,在控制器中我有这样的内容:

 public class DeduccionController : Controller
{

    private IGenericService<Deducciones> service;

    public DeduccionController()
    {
        service = ServiceFactoryGeneric<Deducciones>.InitGenericService(GetClaimsUser.Cadena);
        //GetClaimsUser.Cadena has the name of the connectionString
        //ServiceFactoryGeneric<Deducciones>.InitGenericService do this:
        // return new GenericService<T>(connectionString);
    }

现在我想要而不是拥有自己的工厂我想要使用Ioc容器而且我选择了团结,我是新手,我已经阅读了一些文章,我认为我是基础但基本但是我不知道如何在用户登录后传递连接字符串,因为我的RegisterTypes在应用程序启动时出现

 public static void RegisterTypes(IUnityContainer container)
    {
        // this happen at application start
        // string nameOfConnectionString = *user is still not loged in*
        container.RegisterType<IGenericService<T>, GenericService<T>>(
              new InjectionConstructor(nameOfConnectionString));
    }

我一直在考虑尝试在用户插入之后发布用于注册我的类型的代码,但我不认为这是一个好主意..

我也一直在考虑向我的IGenericService添加一个公共方法,这样我就可以在构造服务之后设置我的connectionString并实现如下:

public void SetConnectionString(string nameOfConnectionString)
{ 
   Db.Database.Connection.ConnectionString = nameOfConnectionString;
   //not sure if this actually works
}

然后我的控制器会是这样的:

  public class DeduccionController : Controller
{

    private IGenericService<Deducciones> _service;

    public DeduccionController(IGenericService<Deducciones> service)
    {
        _service = service;
        _service.SetConnectionString(GetUserClaims.Cadena);
    }

让我的RegisterTypes只包含:

container.RegisterType<IGenericService<T>, GenericService<T>>()

但是因为我对IoC的这个世界不熟悉,我不确定这是否是最好的方式

使用Unity执行此操作的正确方法是什么? 谢谢你的阅读。 我很抱歉我的英语不是我的第一个语言。

1 个答案:

答案 0 :(得分:1)

我最近必须通过根据指定地理位置的路由参数交换连接字符串来做类似的事情。

我建议您构建自己的Unity LifetimeManager,它在每个会话范围的实例中起作用。注册一个对象,该对象充当连接字符串属性的配置容器。

[请参阅Unity Lifetime Manager:http://msdn.microsoft.com/en-us/library/microsoft.practices.unity.lifetimemanager(v=pandp.30).aspx]

然后,您可以将此配置对象的单例实例注入控制器,并在用户登录后设置连接字符串属性。然后,您可以将相同的单例实例注入到使用连接字符串实例化DbContext的DbContext工厂中在配置对象中指定。

就像我说的,它可能不是最优雅的解决方案,但我更喜欢它,而不是必须通过应用程序堆栈的许多层传递连接字符串。希望这会有所帮助。