framework first entityframework create connectionstrings code change c# entity-framework machine-config

c# - first - Cadenas de conexión para Entity Framework



entity framework connection string sql server (6)

Desafortunadamente, la combinación de múltiples contextos de entidades en una única conexión nombrada no es posible. Si desea usar cadenas de conexión con nombre de un archivo .config para definir sus conexiones de Entity Framework, cada una tendrá que tener un nombre diferente. Por convención, ese nombre suele ser el nombre del contexto:

<add name="ModEntity" connectionString="metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" /> <add name="Entity" connectionString="metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SOMESERVER;Initial Catalog=SOMECATALOG;Persist Security Info=True;User ID=Entity;Password=Entity;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

Sin embargo, si terminas con conflictos de espacio de nombres, puedes usar cualquier nombre que desees y simplemente pasar el nombre correcto al contexto cuando se genera:

var context = new Entity("EntityV2");

Obviamente, esta estrategia funciona mejor si está utilizando una inyección de fábrica o de dependencia para producir sus contextos.

Otra opción sería producir la cadena de conexión completa de cada contexto programáticamente y luego pasar la cadena completa al constructor (no solo el nombre).

// Get "Data Source=SomeServer..." var innerConnectionString = GetInnerConnectionStringFromMachinConfig(); // Build the Entity Framework connection string. var connectionString = CreateEntityConnectionString("Entity", innerConnectionString); var context = new EntityContext(connectionString);

Qué tal algo como esto:

Type contextType = typeof(test_Entities); string innerConnectionString = ConfigurationManager.ConnectionStrings["Inner"].ConnectionString; string entConnection = string.Format( "metadata=res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl;provider=System.Data.SqlClient;provider connection string=/"{1}/"", contextType.Name, innerConnectionString); object objContext = Activator.CreateInstance(contextType, entConnection); return objContext as test_Entities;

... con lo siguiente en su machine.config:

<add name="Inner" connectionString="Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />

De esta manera, puede usar una sola cadena de conexión para cada contexto en cada proyecto en la máquina.

Quiero compartir la misma información de la base de datos en varias entidades en Silverlight ... pero quiero que la cadena de conexión se llame xyz y que todos tengan acceso a esa cadena de conexión desde machine.config ...

La parte de metadatos de las entidades será diferente, ya que no nombré a las entidades del mismo modo.

¿Puedo poner múltiples entidades en esa sección de metadatos?

Aquí hay un ejemplo ... Quiero usar esta cadena de conexión, pero tenga en cuenta que puse varias entidades en la sección de metadatos ...

Básicamente quiero tomar esta cadena de conexión

<add name="XYZ" connectionString="metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

Y esta cadena de conexión

<add name="XYZ" connectionString="metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SOMESERVER;Initial Catalog=SOMECATALOG;Persist Security Info=True;User ID=Entity;Password=Entity;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

Para hacer esta cadena de conexión

<add name="XYZ" connectionString="metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl|res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SOMESERVER;Initial Catalog=SOMECATALOG;Persist Security Info=True;User ID=Entity;Password=SOMEPASSWORD;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

Pero simplemente no funciona. Ningún proyecto puede conectarse a él.

string encConnection = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString; Type contextType = typeof(test_Entities); object objContext = Activator.CreateInstance(contextType, encConnection); return objContext as test_Entities;


En lugar de usar archivos de configuración, puede usar una base de datos de configuración con una tabla de configuración del sistema con ámbito y agregar todas sus configuraciones allí.

CREATE TABLE [dbo].[SystemConfig] ( [Id] [int] IDENTITY(1, 1) NOT NULL , [AppName] [varchar](128) NULL , [ScopeName] [varchar](128) NOT NULL , [Key] [varchar](256) NOT NULL , [Value] [varchar](MAX) NOT NULL , CONSTRAINT [PK_SystemConfig_ID] PRIMARY KEY NONCLUSTERED ( [Id] ASC ) WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF GO ALTER TABLE [dbo].[SystemConfig] ADD CONSTRAINT [DF_SystemConfig_ScopeName] DEFAULT (''SystemConfig'') FOR [ScopeName] GO

Con dicha tabla de configuración puedes crear filas como:

Luego, desde su aplicación dal (s) wrapping EF, puede recuperar fácilmente la configuración del ámbito.
Si no está usando dal (s) y trabajando en el cable directamente con EF, puede crear una Entidad desde la tabla SystemConfig y usar el valor dependiendo de la aplicación en la que se encuentre.


Las aplicaciones de Silverlight no tienen acceso directo a machine.config.


Lo que entiendo es que quieres la misma cadena de conexión con diferentes metadatos en ella. Por lo tanto, puede usar una cadena de conexión como se indica a continuación y reemplazar la parte "". He usado tu conexión determinada en la misma secuencia.

connectionString="<METADATA>provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True&quot;"

Para la primera "metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;" conexión, reemplace <METADATA> con "metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;"

Para la segunda "metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;" conexión, reemplace <METADATA> con "metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;"

Para la tercera "metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl|res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;" conexión, reemplace <METADATA> con "metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl|res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;"

¡Feliz codificación!


Para permitir que el mismo edmx acceda a múltiples bases de datos y proveedores de bases de datos y viceversa, uso la siguiente técnica:

1) Definir un ConnectionManager:

public static class ConnectionManager { public static string GetConnectionString(string modelName) { var resourceAssembly = Assembly.GetCallingAssembly(); var resources = resourceAssembly.GetManifestResourceNames(); if (!resources.Contains(modelName + ".csdl") || !resources.Contains(modelName + ".ssdl") || !resources.Contains(modelName + ".msl")) { throw new ApplicationException( "Could not find connection resources required by assembly: " + System.Reflection.Assembly.GetCallingAssembly().FullName); } var provider = System.Configuration.ConfigurationManager.AppSettings.Get( "MyModelUnitOfWorkProvider"); var providerConnectionString = System.Configuration.ConfigurationManager.AppSettings.Get( "MyModelUnitOfWorkConnectionString"); string ssdlText; using (var ssdlInput = resourceAssembly.GetManifestResourceStream(modelName + ".ssdl")) { using (var textReader = new StreamReader(ssdlInput)) { ssdlText = textReader.ReadToEnd(); } } var token = "Provider=/""; var start = ssdlText.IndexOf(token); var end = ssdlText.IndexOf(''"'', start + token.Length); var oldProvider = ssdlText.Substring(start, end + 1 - start); ssdlText = ssdlText.Replace(oldProvider, "Provider=/"" + provider + "/""); var tempDir = Environment.GetEnvironmentVariable("TEMP") + ''//' + resourceAssembly.GetName().Name; Directory.CreateDirectory(tempDir); var ssdlOutputPath = tempDir + ''//' + Guid.NewGuid() + ".ssdl"; using (var outputFile = new FileStream(ssdlOutputPath, FileMode.Create)) { using (var outputStream = new StreamWriter(outputFile)) { outputStream.Write(ssdlText); } } var eBuilder = new EntityConnectionStringBuilder { Provider = provider, Metadata = "res://*/" + modelName + ".csdl" + "|" + ssdlOutputPath + "|res://*/" + modelName + ".msl", ProviderConnectionString = providerConnectionString }; return eBuilder.ToString(); } }

2) Modifique el T4 que crea su ObjectContext para que use el ConnectionManager:

public partial class MyModelUnitOfWork : ObjectContext { public const string ContainerName = "MyModelUnitOfWork"; public static readonly string ConnectionString = ConnectionManager.GetConnectionString("MyModel");

3) Agregue las siguientes líneas a App.Config:

<?xml version="1.0" encoding="utf-8"?> <configuration> <connectionStrings> <add name="MyModelUnitOfWork" connectionString=... /> </connectionStrings> <appSettings> <add key="MyModelUnitOfWorkConnectionString" value="data source=MyPc/SqlExpress;initial catalog=MyDB;integrated security=True;multipleactiveresultsets=True" /> <add key="MyModelUnitOfWorkProvider" value="System.Data.SqlClient" /> </appSettings> </configuration>

ConnectionManager reemplazará ConnectionString y Provider a lo que sea que esté en App.Config.

Puede usar el mismo ConnectionManager para todos los ObjectContexts (para que todos lean la misma configuración de App.Config), o edite el T4 para que cree un ConnectionManager para cada uno (en su propio espacio de nombres), para que cada uno lea la configuración por separado.


Primero intente entender cómo funciona la cadena de conexión de Entity Framework, luego tendrá una idea de lo que está mal.

  1. Tienes dos modelos diferentes, Entity y ModEntity.
  2. Esto significa que tiene dos contextos diferentes, cada contexto tiene su propio Modelo de almacenamiento, Modelo conceptual y mapeo entre ambos.
  3. Simplemente ha combinado cadenas, pero ¿cómo sabrá el contexto de Entity que tiene que seleccionar entity.csdl y ModEntity recogerá modentity.csdl? Bueno, alguien podría escribir algún código inteligente, pero no creo que ese sea el rol principal del equipo de desarrollo de EF.
  4. También machine.config es una mala idea.
  5. Si las aplicaciones web se mueven a una máquina diferente, a un entorno de alojamiento compartido o para fines de mantenimiento, pueden surgir problemas.
  6. Todo el mundo podrá acceder, lo estás haciendo inseguro. Si alguien puede implementar una aplicación web o cualquier aplicación .NET en el servidor, obtendrán acceso completo a su cadena de conexión, incluida la información confidencial de su contraseña.

Otra alternativa es que puede crear su propio constructor para su contexto y pasar su propia cadena de conexión, y puede escribir algunas condiciones, si es así, para cargar los valores predeterminados de web.config

Lo mejor sería hacerlo, dejar las cadenas de conexión tal como están, dar a su grupo de aplicaciones una identidad que tendrá acceso a su servidor de base de datos y no incluir el nombre de usuario y la contraseña dentro de la cadena de conexión.