我正在开发一个应用程序,它将跨多个数据库使用相同的数据库架构。出于这个原因,我创建了一个名为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
?或者我完全错过了什么?我谷歌的所有内容都显示了一个重载,应该允许传入连接字符串。但是,我没有可用的超载。
答案 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)
这是我在构建解决方案时逐步使用的步骤:
这时,已经创建了一个新的.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>