Marco de entidad de instalación para cadena de conexión dinámica

Estoy trabajando en una aplicación que usará el mismo esquema de base de datos en múltiples bases de datos. Por esta razón, he creado una base de datos llamada MyTemplate . Cuando se crea un nuevo usuario, tendrá su propia instancia de la base de datos. Entonces, se MyTemplate_[UserName] una base de datos llamada MyTemplate_[UserName] . Cuando un usuario inicia sesión, necesito señalar sus consultas a su base de datos. Por esta razón, sé que necesito establecer la cadena de conexión en tiempo de ejecución. Mi problema es que también quiero usar Entity Framework.

Actualmente, creé un nuevo .edmx usando MyTemplate como fuente. Pensé que podría actualizar el código y establecer la cadena de conexión allí. Lamentablemente, no puedo encontrar la manera de configurarlo. El constructor de TemplateEntities no tiene una sobrecarga que me permita pasar una cadena de conexión. Noté que TemplateEntities se derivó de DbContext, no creo que este sea el problema.

 string connectionString = GetUsersConnectionString(); using (TemplateEntities entities = new TemplateEntities()) { TemplateEntity entity = new TemplateEntity(); // Save to the database entities.TemplateEntity.Add(entity); entities.SaveChanges(); } 

¿Estoy creando el .edmx incorrectamente? ¿O me estoy perdiendo algo por completo? Todo lo que Google muestra una sobrecarga que debería permitir que se pase una cadena de conexión. Sin embargo, no tengo esa sobrecarga disponible.

La clase TemplateEntities generada se marca como partial .

Todo lo que tiene que hacer es agregar otro archivo con otra parte de la definición de clase parcial que expone el constructor que desea usar:

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

Luego pasa tu cadena de conexión a este constructor.

Desea poner este código en un archivo diferente para que no se sobrescriba al actualizar su modelo de edmx.

La respuesta de Nicholas Butler es bastante correcta. Además de lo que dijo, me enfrenté al problema de tomar una cadena de conexión existente para el marco de trabajo de la entidad y simplemente apuntarla a una base de datos diferente que tenía la misma estructura. Usé el siguiente código para cambiar solo la fuente de datos de la cadena existente:

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

Este es el paso por paso que he usado al construir mis soluciones:

  1. En su proyecto deseado, asegúrese de que se haya instalado Entity Framework usando el menú de opciones “Gestionar paquetes Nuget …”.
  2. En su proyecto deseado, haga clic derecho, luego Agregar-> Nuevo elemento, vaya a Datos y seleccione ADO.NET Entity Data Model.
  3. Escriba el nombre del modelo, digamos “ExampleModel”. Haga clic en Agregar.
  4. Aparecerán cuatro opciones para elegir el contenido del Modelo; generalmente selecciono el primero para construir el modelo a partir de objetos existentes de la base de datos. Haga clic en Siguiente.
  5. Configura tu conexión de datos. Una vez hecho esto, escriba el nombre de su entidad modelo, digamos “ExampleModelEntities”, haga clic en Siguiente.
  6. Seleccione los objetos de la base de datos que estará presente en su modelo EF. En el cuadro de entrada Espacio de nombre de modelo escriba el mismo nombre de modelo desde el Paso 3 (“Ejemplo de modelo”). Haga clic en Finalizar.

En este punto, se ha creado y agregado un nuevo archivo .edmx al proyecto, que contiene todos sus objetos listos para funcionar. Solo el detalle no deseado es, hasta ahora, la cadena de conexión ha sido especificada y guardada en el archivo Web.config de nuestro proyecto.

Para eliminar esto, solo vaya al bloque de sección de su Web.config y elimine los detalles de allí. Ahora trabajaremos en hacer que la cadena de conexión sea legible dinámicamente desde otras fonts.

Como señaló Nicholas Butler, lo siguiente será crear una “versión” de la clase de entidad parcial original creada (ExampleModelEntities), que nos permitirá pasar la cadena de conexión dinámica. Esto es posible ya que la clase de entidad original creada hereda de DBContext que es el que contiene el constructor para pasar tal conexión.

Para hacer lo anterior, agrega una nueva clase vacía a tu proyecto. Asegúrese de escribir el mismo nombre provisto en el Paso 5, siguiendo nuestro caso de estudio “ExampleModelEntities”. Debajo del código para implementar:

DO#

 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 

En este momento, su código está listo para trabajar con cadenas de conexión dinámicas provenientes de otras fonts. Una de estas fonts podría estar pasando una cadena de conexión procedente de otro campo almacenado en una base de datos diferente o utilizando la clase EntityConnectionStringBuilder .

El siguiente ejemplo se implementa en VB.Net, pero utilice alguna herramienta como Telerik para traducir. Digamos que estamos obteniendo una lista de objetos de una determinada base de datos, solo que queremos pasar dinámicamente la cadena de conexión proveniente de otro campo almacenado en una base de datos diferente. Para lograr esto, el código se vería de la siguiente manera:

 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 

Donde Configuration.CONNECTION_STRING es el valor de la cadena de conexión dinámica, expresada mediante un Módulo denominado “Configuración” y una función que recupera dicho valor.

Para evitar imprecisiones de formato, el valor debe almacenarse utilizando el siguiente formato:

Para la autenticación de Windows utilizando Entity Framework:

 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"' 

Para autenticación SQL utilizando Entity Framework:

 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"' 

Finalmente, extendiendo la respuesta proporcionada por Mark, en Microsoft hay una explicación detallada sobre cómo trabajar con la clase EntityConnectionStringBuilder, que también se puede usar para construir cadenas de conexión dinámicas y luego pasar este valor a pedido.