25

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

目前,我使用 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不正确吗?还是我完全错过了什么?我谷歌的所有内容都显示了一个应该允许传入连接字符串的重载。但是,我没有可用的重载。

4

3 回答 3

44

生成的TemplateEntities类标记为partial

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

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

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

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

于 2013-01-21T14:32:19.083 回答
17

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

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))
{
    ...
}
于 2013-12-11T21:04:41.667 回答
0

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

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

此时,已创建一个新的 .edmx 文件并将其添加到项目中,其中包含所有准备工作的对象。只有不想要的细节是,到目前为止,连接字符串已被指定并保存到我们项目的 Web.config 文件中。

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

正如 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是动态连接字符串的值,使用名为“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 提供的答案,在微软有一个关于如何使用 EntityConnectionStringBuilder 类的详细解释,它也可以用来构建动态连接字符串,然后按需传递这个值。

于 2018-08-17T18:18:27.477 回答