动态连接字符串的设置实体框架

时间:2013-01-21 14:25:08

标签: c# entity-framework

我正在开发一个应用程序,它将跨多个数据库使用相同的数据库架构。出于这个原因,我创建了一个名为MyTemplate的数据库。创建新用户时,他们将拥有自己的数据库实例。因此,将创建一个名为MyTemplate_[UserName]的数据库。当用户登录时,我需要将他们的查询指向他们的数据库。出于这个原因,我知道我需要在运行时设置连接字符串。我的问题是,我也想使用实体框架。

目前,我使用MyTemplate作为源创建了一个新的.edmx。我以为我能够更新代码并在那里设置连接字符串。不幸的是,我无法弄清楚如何设置它。 TemplateEntities的构造函数没有允许我传入连接字符串的重载。我注意到TemplateEntities派生自DbContext,我认为这不是问题。

string connectionString = GetUsersConnectionString();
using (TemplateEntities entities = new TemplateEntities())
{
  TemplateEntity entity = new TemplateEntity();

  // Save to the database
  entities.TemplateEntity.Add(entity);
  entities.SaveChanges();
}

我是否错误地创建了.edmx?或者我完全错过了什么?我谷歌的所有内容都显示了一个重载,应该允许传入连接字符串。但是,我没有可用的超载。

3 个答案:

答案 0 :(得分:38)

生成的TemplateEntities类标记为partial

您所要做的就是添加另一个文件,该部分类定义的另一部分公开您要使用的构造函数:

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

然后将您的连接字符串传递给此构造函数。

您希望将此代码放在不同的文件中,以便在更新edmx模型时不会覆盖该代码。

答案 1 :(得分:16)

尼古拉斯·巴特勒的回答非常正确。除了他所说的,我还面临着为实体框架获取现有连接字符串并将其指向具有相同结构的不同数据库的问题。我使用以下代码仅更改现有字符串的数据源:

var originalConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["CSName"].ConnectionString;
var ecsBuilder = new EntityConnectionStringBuilder(originalConnectionString);
var sqlCsBuilder = new SqlConnectionStringBuilder(ecsBuilder.ProviderConnectionString)
{
    DataSource = "newDBHost"
};
var providerConnectionString = sqlCsBuilder.ToString();
ecsBuilder.ProviderConnectionString = providerConnectionString;

string contextConnectionString = ecsBuilder.ToString();
using (var db = new SMSContext(contextConnectionString))
{
    ...
}

答案 2 :(得分:0)

这是我在构建解决方案时逐步使用的步骤:

  1. 在所需的项目上,确保使用“管理Nuget软件包...”选项菜单安装了Entity Framework。
  2. 在所需的项目上,右键单击,然后单击“添加”->“新项目”,转到“数据”,然后选择“ ADO.NET实体数据模型”。
  3. 键入模型的名称,例如“ ExampleModel”。点击添加。
  4. 出现四个选项以选择“模型”内容,我通常选择第一个,以便从数据库中的现有对象构建模型。单击下一步。
  5. 设置您的数据连接。完成后,键入模型实体的名称,假设为“ ExampleModelEntities”,然后单击“下一步”。
  6. 从数据库中选择将出现在EF模型上的对象。在“模型名称空间”输入框中,输入与步骤3相同的模型名称(“ ExampleModel”)。单击完成。

这时,已经创建了一个新的.edmx文件并将其添加到项目中,其中包含准备就绪的所有对象。到目前为止,仅指定了不需要的详细信息,并且已将连接字符串指定并保存到我们项目的Web.config文件中。

要删除它,只需转到Web.config的<connectionStrings></connectionStrings>部分,然后从那里删除详细信息。现在,我们将努力使连接字符串可从其他来源动态读取。

正如尼古拉斯·巴特勒(Nicholas Butler)指出的那样,下一步将是创建所创建的原始局部实体类(ExampleModelEntities)的“版本”,这将使我们能够传递动态连接字符串。这是可能的,因为创建的原始实体类是从DBContext继承的,DBContext是包含传递此类连接的构造函数的类。

要执行上述操作,请向您的项目添加一个新的空类。在案例研究“ ExampleModelEntities”之后,请确保键入在步骤5中提供的相同名称。下面的代码要实现:

C#

public partial class ExampleModelEntities
{
public ExampleModelEntities(string connString) : base(connString)
{

}
}

VB.Net:

Partial Public Class ExampleModelEntities

Public Sub New(ByVal connString As String)
    MyBase.New(connString)
End Sub
End Class

目前,您的代码已准备好与其他来源的动态连接字符串一起使用。这些来源之一可能是传递来自存储在不同数据库中的另一个字段的连接字符串,或者使用 EntityConnectionStringBuilder 类。

下面的示例在VB.Net中实现,但是请使用诸如Telerik之类的工具进行翻译。假设我们正在从某个数据库中获取对象列表,只是我们要动态传递来自存储在不同数据库中的另一个字段的连接字符串。为此,代码如下所示:

Public Shared Function Get_List(ByVal Param1 As String) As List(Of Stored_Procedure_Code_Result)

Try

Dim Object_List_Result As List(Of Stored_Procedure_Code_Result) = Nothing

Using dbContext As New ExampleModelEntities(Configuration.CONNECTION_STRING)

Object_List_Result = dbContext.Stored_Procedure_Code(Param1).ToList

dbContext.Dispose()
End Using
Return Object_List_Result

Catch ex As Exception
Throw ex
End Try

End Function

其中 Configuration.CONNECTION_STRING 是动态连接字符串的值,使用称为“配置”的模块和检索该值的函数来表示。

为了避免格式不正确,应使用以下格式存储值:

对于使用Entity Framework的Windows身份验证:

UPDATE [DBConnections].[dbo].[ListOfConnectionsTable]
SET ConnValue = 'metadata=res://*/ExampleModel.csdl|res://*/ExampleModel.ssdl|res://*/ExampleModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=ServerName;Initial Catalog=DBName;Integrated Security=True"'

对于使用实体框架的SQL身份验证:

UPDATE [DBConnections].[dbo].[ListOfConnectionsTable]
SET ConnValue = 'metadata=res://*/ExampleModel.csdl|res://*/ExampleModel.ssdl|res://*/ExampleModel.msl;provider=System.Data.SqlClient;provider connection string="Persist Security Info=False;User ID=XXXXXX;Password=XXXXXXX;Initial Catalog=DBName;Data Source=ServerName;App=YourAppName;Network Library=dbmssocn"'

最后,在Microsoft处扩展了Mark提供的答案,详细说明了如何使用EntityConnectionStringBuilder类,该类还可用于构建动态连接字符串,然后按需传递此值。 / p>