Подтвердить что ты не робот

Строки подключения для платформы Entity

Я хочу поделиться одной и той же базой данных между несколькими объектами в Silverlight.. но я хочу, чтобы строка соединения называлась xyz и каждый из них получил доступ к этой строке соединения из machine.config...

Часть метаданных объектов будет отличаться, так как я не назвал объекты такими же.

Можно ли поместить несколько объектов в этот раздел метаданных?

Вот пример. Я хочу использовать эту строку подключения, но обратите внимание, что я помещаю несколько объектов в раздел метаданных.

В принципе, я хочу использовать эту строку соединения

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

И эта строка подключения

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

Чтобы создать эту строку соединения

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

Но это просто не работает. Ни один проект не может подключиться к нему.

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

Ответ 1

К сожалению, объединение нескольких контекстов объектов в одно и то же соединение не представляется возможным. Если вы хотите использовать именованные строки подключения из файла .config для определения своих соединений Entity Framework, каждый из них должен иметь другое имя. По соглашению, это имя обычно является именем контекста:

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

Однако, если вы столкнулись с конфликтами пространства имен, вы можете использовать любое имя, которое хотите, и просто передать правильное имя контексту при его создании:

var context = new Entity("EntityV2");

Очевидно, что эта стратегия работает лучше всего, если вы используете либо factory, либо инъекцию зависимостей для создания ваших контекстов.

Другой вариант заключается в том, чтобы программно создать каждую строку целых соединений, а затем передать всю строку в конструктор (а не только имя).

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

Как насчет чего-то вроде этого:

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; 

... со следующим в файле 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" />

Таким образом, вы можете использовать одну строку соединения для каждого контекста в каждом проекте на машине.

Ответ 2

Вместо использования конфигурационных файлов вы можете использовать базу данных конфигурации с областью действия systemConfig и добавить все свои настройки.

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 

В такой таблице конфигурации вы можете создавать такие строки: enter image description here

Затем из вашего приложения dal (s) wrapping EF вы можете легко получить измененную конфигурацию.
Если вы не используете dal (s) и работаете в проводнике напрямую с EF, вы можете сделать Entity из таблицы SystemConfig и использовать значение в зависимости от приложения, в котором вы находитесь.

Ответ 3

Сначала попробуйте понять, как работает строка Connection Entity Framework, тогда вы получите представление о том, что не так.

  • У вас есть две разные модели: Entity и ModEntity
  • Это означает, что у вас есть два разных контекста, каждый контекст имеет свою собственную модель хранения, концептуальную модель и сопоставление между ними.
  • Вы просто комбинировали строки, но как контекст Entity будет знать, что он должен пикать entity.csdl и ModEntity будет pickup modentity.csdl? Ну, кто-то мог написать какой-то интеллектуальный код, но я не думаю, что это основная роль команды разработчиков EF.
  • Также machine.config - плохая идея.
  • Если веб-приложения перемещаются на другую машину или в среду совместного размещения или для целей обслуживания, это может привести к проблемам.
  • Каждый сможет получить к нему доступ, вы делаете его небезопасным. Если кто-либо может развернуть веб-приложение или любое приложение .NET на сервере, они получат полный доступ к вашей строке подключения, включая информацию о вашем конфиденциальном пароле.

Другой вариант: вы можете создать свой собственный конструктор для своего контекста и передать свою собственную строку соединения, и вы можете написать какое-либо условие if и т.д. для загрузки значений по умолчанию из web.config

Лучше всего было бы: оставить строки подключения так, как есть, дать вашему пулу приложений идентификатор, который будет иметь доступ к вашему серверу базы данных и не включать имя пользователя и пароль в строку подключения.

Ответ 4

Чтобы включить тот же edmx для доступа к нескольким базам данных и поставщикам баз данных, и наоборот, я использую следующий метод:

1) Определите 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) Измените T4, который создает объект ObjectContext, чтобы он использовал ConnectionManager:

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

3) Добавьте в 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 заменит ConnectionString и Provider тем, что когда-либо было в App.Config.

Вы можете использовать один и тот же ConnectionManager для всех объектов ObjectContext (чтобы все они читали одни и те же настройки из App.Config) или редактировали T4, поэтому он создает один ConnectionManager для каждого (в своем собственном пространстве имен), так что каждый считывает отдельные настройки.

Ответ 5

Я понимаю, что вы хотите использовать такую ​​же строку соединения с разными метаданными. Таким образом, вы можете использовать строку соединения, как указано ниже, и заменить часть "". Я использовал ваш данный connectionString в той же последовательности.

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

Для первого соединенияString замените <METADATA> на "metadata=res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;"

Для второго connectionString замените <METADATA> на "metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl;"

Для третьего connectionString замените <METADATA> на "metadata=res://*/Entity.csdl|res://*/Entity.ssdl|res://*/Entity.msl|res://*/ModEntity.csdl|res://*/ModEntity.ssdl|res://*/ModEntity.msl;"

Счастливое кодирование!

Ответ 6

Приложения Silverlight не имеют прямого доступа к machine.config.