Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 设置动态连接字符串的实体框架_C#_Entity Framework - Fatal编程技术网

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

C# 设置动态连接字符串的实体框架,c#,entity-framework,C#,Entity Framework,我正在开发一个应用程序,它将在多个数据库中使用相同的数据库模式。因此,我创建了一个名为MyTemplate的数据库。创建新用户时,他们将拥有自己的数据库实例。因此,将创建一个名为MyTemplate\uuuu[UserName]的数据库。当用户登录时,我需要将他们的查询指向他们的数据库。由于这个原因,我知道我需要在运行时设置连接字符串。我的问题是,我还想使用实体框架 目前,我使用MyTemplate作为源创建了一个新的.edmx。我想我可以更新代码并在那里设置连接字符串。不幸的是,我不知道如何设

我正在开发一个应用程序,它将在多个数据库中使用相同的数据库模式。因此,我创建了一个名为
MyTemplate
的数据库。创建新用户时,他们将拥有自己的数据库实例。因此,将创建一个名为
MyTemplate\uuuu[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
?还是我完全错过了什么?我在Google上搜索的所有内容都显示了一个重载,应该允许传入连接字符串。但是,我没有可用的重载。

生成的
TemplateEntities
类被标记为
partial

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

partial class TemplateEntities
{
  public TemplateEntities( string nameOrConnectionString )
    : base( nameOrConnectionString )
  {
  }
}
然后将连接字符串传入此构造函数


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

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

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

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

  • 在所需的项目上,确保使用“管理Nuget软件包…”选项菜单安装了Entity Framework
  • 在所需的项目上,单击鼠标右键,然后单击“添加”->“新建项”,转到“数据”并选择“ADO.NET实体数据模型”
  • 键入模型的名称,例如“ExampleModel”。单击添加
  • 将出现四个选项来选择模型内容,我通常选择第一个,以便从数据库中的现有对象构建模型。单击下一步
  • 设置数据连接。完成后,键入模型实体的名称,例如“ExampleModelEntities”,单击下一步
  • 从数据库中选择将出现在EF模型上的对象。在模型名称空间输入框中,键入步骤3中相同的模型名称(“ExampleModel”)。单击Finish
  • 此时,已创建一个新的.edmx文件并将其添加到项目中,其中包含所有准备工作的对象。唯一不需要的细节是,到目前为止,已指定连接字符串并将其保存到项目的Web.config文件中

    要删除此项,只需转到Web.config的
    部分块并从中删除详细信息。现在,我们将致力于使连接字符串能够从其他源动态读取

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

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

    C#

    VB.Net:

    Partial Public Class ExampleModelEntities
    
    Public Sub New(ByVal connString As String)
        MyBase.New(connString)
    End Sub
    End Class
    
    此时,您的代码已准备好使用来自其他源的动态连接字符串。其中一个源可以传递来自另一个存储在不同数据库上的字段的连接字符串,或者使用EntityConnectionStringBuilder类

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

    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身份验证:

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


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

    当我这样做时,我收到一个错误,它说:“对象”不包含接受1个参数的构造函数。我做错了什么?带有新构造函数的部分类定义必须与生成的类位于同一命名空间中-否则它将声明一个新类(默认情况下派生自
    对象
    )+1:我对这种类型的构造函数为什么不在默认模板中感到困惑,但这是一个很好且干净的解决方案,thx.@NicholasButler这个方法是否适用于模式优先方法?我给了类似的参数my connectionString,但是当我试图查询数据库时,我得到了一个错误!这是我放置更多详细信息的链接:这些类是
    EntityConnectionStringBuilder&SqlConnectionStringBuilder
    dotnet内置类或由u@MonojitSarkar编写的类它们是.NET类,而不是wri类
    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
    
    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"'
    
    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"'