实体框架6设置连接字符串运行时

时间:2015-04-03 22:16:30

标签: .net entity-framework entity-framework-6

我们处于混合环境中,我们的应用程序同时使用ADO.NET和实体框架 由于两者都指向相同的物理SQL服务器,我们希望从配置文件中删除Entity Framework连接字符串,然后根据当前的ADO.NET连接字符串自动构建字符串。
这样可以避免开发人员更改ADO.NET字符串但忘记更改Entity Framework连接字符串的错误。

我读过这篇文章,但他们没有回答这个问题 How do I create connection string programmatically to MS SQL in Entity Framework 6?

如果我创建自己的DbConnection并将其传递给DbContext(existingConnection,contextOwnsConnection),那么它会抛出错误"上下文正在Code First模式中使用,该代码是从EDMX文件为数据库生成的First或Model First开发。"

我没有使用Code First。

https://msdn.microsoft.com/en-us/data/jj680699
这里讨论了EF 6中的代码库配置,但文章没有显示任何实际更改连接字符串的代码。

更新:有助于澄清我的问题的更多信息。
我不是先使用代码,而是想在配置文件之外构建一个连接字符串 我正在使用的DbContext是T4模板生成的自动生成的DbContext文件的部分类。
我的印象是我需要创建一个继承的DbConfiguration类并在该类中执行某些操作,但我找到的唯一示例是使用Azure。 https://msdn.microsoft.com/en-us/data/jj680699
有一篇关于Code Project的文章讨论了在运行时设置连接字符串,但本文基于每次创建新的Entity容器时构建连接字符串。
http://www.codeproject.com/Tips/234677/Set-the-connection-string-for-Entity-Framework-at

我希望能够使用我的部分DbContext类来创建连接字符串,以便调用者不必执行任何特殊操作。

更新:RunTime的工作代码,但不是DesignTime的工作代码
使用@Circular Reference"下面列出的代码",我能够更改连接字符串而不更改对我的Entity类的调用但是这对DesignTime EDMX文件不起作用。

public partial class TestEntities : DbContext
{
    public TestEntities() : base(GetSqlConnection(), true)
    {
    }

    public static DbConnection GetSqlConnection()
    {
        // Initialize the EntityConnectionStringBuilder. 
        EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();

        var connectionSettings = ConfigurationManager.ConnectionStrings("Current_ADO_Connection_In_Config");

        // Set the provider name. 
        entityBuilder.Provider = connectionSettings.ProviderName;

        // Set the provider-specific connection string. 
        entityBuilder.ProviderConnectionString = connectionSettings.ConnectionString;

        // Set the Metadata location. 
        entityBuilder.Metadata = "res://*/Models.TestModel.csdl|res://*/Models.TestModel.ssdl|res://*/Models.TestModel.msl";

        return new EntityConnection(entityBuilder.ToString());
    }
}

现在,如果我能让DesignTime正常工作,那就更好了。

3 个答案:

答案 0 :(得分:21)

您可以使用配置文件中的连接字符串在设计时工作。

<add name="DWContext" connectionString="metadata=res://*/Database.DWH.DWModel.csdl|res://*/Database.DWH.DWModel.ssdl|res://*/Database.DWH.DWModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=SQLSERVER_INSTANCE;initial catalog=DB_NAME;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

所以不要删除它,因为只在设计时才需要它。

使用此方法(类似于上一个方法)在运行时以动态方式工作:

扩展数据上下文分部类:

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

    /// <summary>
    /// Create a new EF6 dynamic data context using the specified provider connection string.
    /// </summary>
    /// <param name="providerConnectionString">Provider connection string to use. Usually a standart ADO.NET connection string.</param>
    /// <returns></returns>
    public static DWContext Create(string providerConnectionString)
    {
        var entityBuilder = new EntityConnectionStringBuilder();

        // use your ADO.NET connection string
        entityBuilder.ProviderConnectionString = providerConnectionString;

        entityBuilder.Provider = "System.Data.SqlClient";

        // Set the Metadata location.
        entityBuilder.Metadata = @"res://*/Database.DWH.DWModel.csdl|res://*/Database.DWH.DWModel.ssdl|res://*/Database.DWH.DWModel.msl";

        return new DWContext(entityBuilder.ConnectionString);
    }

}

从您的代码中创建一个新的EF数据上下文:

private DWContext db = DWContext.Create(providerConnectionString);

Ciao; - )

答案 1 :(得分:13)

您将获得Code First模式异常,因为您传递的是使用ADO.NET连接字符串构建的DbConnection。此连接字符串不包含对元数据文件的引用,因此EntityFramework不知道在哪里找到它们。

要使用适当的编程设置连接字符串创建DbContext,请使用EntityConnectionStringBuilder类。

var entityBuilder = new EntityConnectionStringBuilder();

// use your ADO.NET connection string
entityBuilder.ProviderConnectionString = conString;

// Set the Metadata location.
entityBuilder.Metadata = @"res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl";
var dbContext = new DbContext(entityBuilder.ConnectionString);

答案 2 :(得分:0)

另一种方法是在配置文件中声明另一个连接字符串,并将其与以下替代构造函数一起使用:

class TestEntities : DbConnect {
 
    public TestEntities (string connectionName)
       : base($"name={connectionName}")
    {
    }

...

然后仅使用此解决方案:

  1. 将另一个连接添加到配置文件:
 <add name="other" connectionString="metadata=res://*/Data.TestEntities .csdl|res://*/Data.TestEntities .ssdl|res://*/Data.TestEntities .msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=...;initial catalog=...;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  1. 这样称呼它:

    var db = new TestEntities (connectionName:"other");