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

本文关键字:实体 框架 设置 字符串 动态 连接 | 更新日期: 2023-09-27 17:54:45

我正在开发一个应用程序,该应用程序将在多个数据库中使用相同的数据库模式。出于这个原因,我创建了一个名为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是否错误?还是我完全错过了什么?所有我谷歌显示超载,应该允许连接字符串传入。但是,我没有这个过载可用。

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

生成的TemplateEntities类标记为partial

你所要做的就是添加另一个文件,其中包含部分类定义的另一部分,该部分类定义公开了你想使用的构造函数:

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

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

您希望将此代码放在另一个文件中,以便在更新edmx模型时不会被覆盖。

Nicholas Butler的回答非常正确。除了他所说的,我还面临着一个问题,即为实体框架提供一个现有的连接字符串,并将其指向具有相同结构的不同数据库。我使用以下代码仅更改现有字符串的数据源:

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))
{
    ...
}

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

  1. 在你想要的项目上,确保使用"Manage Nuget Packages…"选项菜单安装实体框架。
  2. 在您想要的项目上,右键单击,然后添加->新建项目,转到数据并选择ADO。. NET实体数据模型输入模型的名称,比如"ExampleModel"。单击Add。
  3. 选择模型内容会出现四个选项,我通常选择第一个,以便从数据库中的现有对象构建模型。单击Next。
  4. 设置数据连接。完成后,键入模型实体的名称,比如"ExampleModelEntities",单击Next。
  5. 从数据库中选择将出现在EF模型上的对象。在Model Namespace输入框中输入与步骤3相同的模型名称("ExampleModel")。单击Finish。
此时,已经创建了一个新的.edmx文件并将其添加到项目中,其中包含所有准备工作的对象。唯一不需要的细节是,到目前为止,连接字符串已经被指定并保存到Web中。项目配置文件

要删除这个,只需到您的Web的<connectionStrings></connectionStrings>节块。配置并删除其中的详细信息。现在我们将使连接字符串从其他源动态可读。

正如Nicholas Butler所指出的,接下来要做的是创建原始部分实体类的"版本"(ExampleModelEntities),这将允许我们传递动态连接字符串。这是可能的,因为创建的原始实体类继承自DBContext, DBContext包含传递这种连接的构造函数。

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

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实现的。,但请使用一些工具,如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

, 配置。CONNECTION_STRING是动态连接字符串的值,使用名为"Configuration"的模块和检索该值的函数表示。

为避免格式错误,应使用以下格式存储该值:

对于使用实体框架的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"'

最后,扩展Mark提供的答案,在Microsoft有一个关于如何使用EntityConnectionStringBuilder类的详细解释,该类也可用于构建动态连接字符串,然后根据需要传递此值