将自定义连接字符串注入实体框架的数据库上下文



我想在我的EF上下文中注入一个自定义连接字符串,而不是在我的web.config中使用连接字符串。这个想法是将MVC项目中所有与数据库相关的逻辑移到一个单独的层中。我还希望这一层负责正确的连接字符串,而不是我的web应用程序。

当前使用上下文的服务正在调用默认构造函数:

using (var context = new MyDbContext()) {
    //...
}

默认构造函数在内部使用web.config的连接字符串的名称调用DbContext:

public partial class MyDbContext : DbContext
{
    public MyDbContext()
        : base("name=MyDbContext")
    {
    }
    //...
}

为了注入我的自定义连接字符串,我需要一个重载的构造函数,它将连接字符串作为参数。不幸的是,没有提供这样的构造函数。

很明显,在MyDbContext类中手动添加构造函数重载将是一个非常糟糕的想法,因为这个类是自动生成的,很快就会被覆盖。我们不要再谈这个了,这是被禁止的。时期。

由于MyDbContext是一个部分类,可以在单独的类文件partial class MyDbContext中添加额外的构造函数,但这似乎也很糟糕。我不知道为什么,但我的大脑说坏主意

经过一些调查,我发现,一个人可以告诉EF包括这个额外的构造函数通过编辑T4模板Model.Context.tt,这是c#和一些模板标记的混合。下面是原始构造函数:

public <#=Code.Escape(container)#>()
    : base("name=<#=container.Name#>")
{
<#
    WriteLazyLoadingEnabled(container);
#>
}

显然很容易添加类似的逻辑来生成包含连接字符串的重载构造函数:

public <#=Code.Escape(container)#>(string nameOrConnectionString)
    : base(nameOrConnectionString)
{
<#
    WriteLazyLoadingEnabled(container);
#>
}

我尝试了一下,并注意到,重新生成模型类和从DB更新模型都将影响T4模板,因此额外的构造函数将始终在那里。好!乍一看,这似乎是一个合适的解决方案,但是……

这是我的问题:这真的是一个好的解决方案吗?

让我们再次比较这三个选项:

  1. 编辑自动生成的类(好吧,我们同意忘记这个)
  2. 在部分类文件中添加构造函数
  3. 编辑T4模板,告诉EF生成额外的构造函数

在这三个选项中,第三个对我来说似乎是最方便和干净的解决方案。你的意见是什么?有人有好的理由吗,为什么这是个坏主意?是否有更多的选项注入连接字符串,也许使用自定义connectionFactory ?如果有,我该怎么做?

像@shaft建议的那样,我将T4模板方法替换为使用分部类。事实证明,这确实比我目前所知道的任何其他解决方案都要简单和直观得多。

自动生成的类看起来像:

public partial class MyDbContext : DbContext
{
    public MyDbContext() : base("name=MyDbContext")
    {
    }
    //...
}

我只是添加了另一个同名的部分类。问题解决了。

public partial class MyDbContext 
{
    public MyDbContext(string nameOrConnectionString)
             : base(nameOrConnectionString) 
    {
    }
}

在你提供的3个选项中,我宁愿选择选项2。难道不是引入了partial关键字来解决自动生成文件的问题吗?在我看来,使用T4模板带来了额外的复杂性,维护开发人员必须多理解一件事(不是每个人都熟悉T4),但是扩展部分类是更标准的c#开发。

然而,我不知道"是否有一个真正好的解决方案"的答案。引入工厂又带来了新的代码来维护、测试和理解,我不确定这个抽象在这里有帮助,因为工厂本身需要用适当的构造函数实例化dbcontext(无论如何你都必须提供)。 编辑:

只是想了一下:工厂可能是有用的,以解决从另一个位置的连接字符串(你说,你不希望在web.config的连接字符串),但这仍然不能解决构造器的问题

相关内容

  • 没有找到相关文章

最新更新