Je souhaite partager les mêmes informations de base de données entre plusieurs entités dans Silverlight .. mais je veux que la chaîne de connexion soit nommée xyz et que tout le monde accède à cette chaîne de connexion à partir de machine.config ...
La partie métadonnées des entités sera différente car je n'ai pas nommé les entités de la même façon.
Puis-je mettre plusieurs entités dans cette section de métadonnées?
Voici un exemple .. Je veux utiliser cette chaîne de connexion mais notez que j'ai mis plusieurs entités dans la section métadonnées ..
Fondamentalement, je veux prendre cette chaîne de connexion
<add name="XYZ" connectionString="metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;provider=System.Data.SqlClient;provider connection string="Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
Et cette chaîne de connexion
<add name="XYZ" connectionString="metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;provider=System.Data.SqlClient;provider connection string="Data Source=SOMESERVER;Initial Catalog=SOMECATALOG;Persist Security Info=True;User ID=Entity;Password=Entity;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
Pour créer cette chaîne de connexion
<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="Data Source=SOMESERVER;Initial Catalog=SOMECATALOG;Persist Security Info=True;User ID=Entity;Password=SOMEPASSWORD;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
Mais cela ne fonctionne tout simplement pas. Aucun des deux projets ne peut s'y connecter.
string encConnection = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
Type contextType = typeof(test_Entities);
object objContext = Activator.CreateInstance(contextType, encConnection);
return objContext as test_Entities;
Malheureusement, la combinaison de plusieurs contextes d'entité en une seule connexion nommée n'est pas possible. Si vous souhaitez utiliser des chaînes de connexion nommées à partir d'un fichier .config pour définir vos connexions Entity Framework, elles devront chacune avoir un nom différent. Par convention, ce nom est généralement le nom du contexte:
<add name="ModEntity" connectionString="metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;provider=System.Data.SqlClient;provider connection string="Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True"" 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="Data Source=SOMESERVER;Initial Catalog=SOMECATALOG;Persist Security Info=True;User ID=Entity;Password=Entity;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
Cependant, si vous vous retrouvez avec des conflits d'espace de noms, vous pouvez utiliser le nom de votre choix et simplement passer le nom correct au contexte lors de sa génération:
var context = new Entity("EntityV2");
Évidemment, cette stratégie fonctionne mieux si vous utilisez une injection d'usine ou de dépendance pour produire vos contextes.
Une autre option serait de produire la chaîne de connexion entière de chaque contexte par programme, puis de passer toute la chaîne au constructeur (pas seulement le nom).
// Get "Data Source=SomeServer..."
var innerConnectionString = GetInnerConnectionStringFromMachinConfig();
// Build the Entity Framework connection string.
var connectionString = CreateEntityConnectionString("Entity", innerConnectionString);
var context = new EntityContext(connectionString);
Que diriez-vous quelque chose comme ça:
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;
... avec les éléments suivants dans votre 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 cette façon, vous pouvez utiliser une chaîne de connexion unique pour chaque contexte dans chaque projet sur la machine.
Au lieu d'utiliser des fichiers de configuration, vous pouvez utiliser une base de données de configuration avec une table systemConfig étendue et y ajouter tous vos paramètres.
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
Avec une telle table de configuration, vous pouvez créer des lignes comme celles-ci:
Ensuite, à partir de votre dal (s) d'application enveloppant EF, vous pouvez facilement récupérer la configuration étendue.
Si vous n'utilisez pas de dal (s) et travaillez directement dans le câble avec EF, vous pouvez créer une entité à partir de la table SystemConfig et utiliser la valeur en fonction de l'application sur laquelle vous vous trouvez.
Essayez d'abord de comprendre comment fonctionne la chaîne de connexion Entity Framework, vous aurez alors une idée de ce qui ne va pas.
Une autre alternative est que vous pouvez créer votre propre constructeur pour votre contexte et passer votre propre chaîne de connexion et vous pouvez écrire une condition if, etc. pour charger les valeurs par défaut à partir de web.config
La meilleure chose à faire serait de laisser les chaînes de connexion telles quelles, de donner à votre pool d'applications une identité qui aura accès à votre serveur de base de données et de ne pas inclure le nom d'utilisateur et le mot de passe dans la chaîne de connexion.
Pour permettre au même edmx d'accéder à plusieurs bases de données et fournisseurs de bases de données et vice versa, j'utilise la technique suivante:
1) Définissez 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) Modifiez le T4 qui crée votre ObjectContext afin qu'il utilise le ConnectionManager:
public partial class MyModelUnitOfWork : ObjectContext
{
public const string ContainerName = "MyModelUnitOfWork";
public static readonly string ConnectionString
= ConnectionManager.GetConnectionString("MyModel");
3) Ajoutez les lignes suivantes à 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 ; sécurité intégrée = True; multipleactiveresultsets = True "/> <add key =" MyModelUnitOfWorkProvider "value =" System.Data.SqlClient "/> </appSettings> < /configuration>
Le ConnectionManager remplacera ConnectionString et Provider par ce qui se trouve dans App.Config.
Vous pouvez utiliser le même ConnectionManager pour tous les ObjectContexts (afin qu'ils lisent tous les mêmes paramètres depuis App.Config), ou modifier le T4 afin qu'il crée un ConnectionManager pour chacun (dans son propre espace de noms), afin que chacun lise des paramètres distincts.
Ce que je comprends, c'est que vous voulez la même chaîne de connexion avec différentes métadonnées. Vous pouvez donc utiliser une chaîne de connexion comme indiqué ci-dessous et remplacer la partie "". J'ai utilisé votre chaîne de connexion donnée dans la même séquence.
connectionString="<METADATA>provider=System.Data.SqlClient;provider connection string="Data Source=SomeServer;Initial Catalog=SomeCatalog;Persist Security Info=True;User ID=Entity;Password=SomePassword;MultipleActiveResultSets=True""
Pour la première connexionString remplacez <METADATA>
avec "metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;"
Pour la deuxième connexionString remplacez <METADATA>
avec "metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;"
Pour la troisième connexion, la chaîne remplace <METADATA>
avec "metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl|res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;"
Bon codage!
Les applications Silverlight n'ont pas d'accès direct à machine.config.