Динамически создавать соединение Entity Framework [duplicate]

Чтобы проверить, содержится ли значение в наборе переменных, вы можете использовать встроенные модули itertools и operator.

Например:

Импорт:

from itertools import repeat
from operator import contains

Объявить переменные:

x = 0
y = 1
z = 3

Создать сопоставление значений (в порядке, который вы хотите проверить):

check_values = (0, 1, 3)

Используйте itertools для разрешить повторение переменных:

check_vars = repeat((x, y, z))

Наконец, используйте функцию map для создания итератора:

checker = map(contains, check_vars, check_values)

Затем при проверке значений (в оригинале порядок), используйте next():

if next(checker)  # Checks for 0
    # Do something
    pass
elif next(checker)  # Checks for 1
    # Do something
    pass

и т. д. ...

Это имеет преимущество перед lambda x: x in (variables), потому что operator является встроенным модулем и работает быстрее, более эффективен, чем при использовании lambda, который должен создать пользовательскую функцию на месте.

Еще одна опция для проверки наличия ненулевого (или False) значения в списке:

not (x and y and z)

Эквивалент:

not all((x, y, z))
24
задан Tim B 4 December 2015 в 17:09
поделиться

6 ответов

К сожалению, объединение нескольких контекстов объектов в одно и то же соединение невозможно. Если вы хотите использовать именованные строки подключения из файла .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");

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

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

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

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

38
ответ дан Tim B 23 August 2018 в 18:27
поделиться

Насколько я понимаю, вы хотите, чтобы в нем была такая же строка соединения с разными метаданными. Таким образом, вы можете использовать строку соединения, как указано ниже, и заменить часть «». Я использовал ваш 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;"

Для первого connectionString замените <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;"

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

1
ответ дан abatishchev 23 August 2018 в 18:27
поделиться

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

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

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

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

2
ответ дан Akash Kava 23 August 2018 в 18:27
поделиться

Чтобы включить тот же 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 для каждого (в собственном пространстве имен), так что каждый считывает отдельные настройки.

2
ответ дан Danny Varod 23 August 2018 в 18:27
поделиться

Вместо использования файлов конфигурации вы можете использовать базу данных конфигурации с таблицей 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 [/g0]

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

5
ответ дан GEOCHET 23 August 2018 в 18:27
поделиться

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

0
ответ дан Michael S. Scherotter 23 August 2018 в 18:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: