EF6 и несколько конфигураций (SQL Server и SQL Server Compact)

Обновление: проблема решена, см. конец этого вопроса.

Проблема:

Мы пытаемся использовать Entity Framework 6 и конфигурацию на основе кода в сценарии, в котором мы использовали как SQL Server, так и SQL Server CE в одном и том же AppDomain.

Этот довольно простой сценарий, похоже, не поддерживается «по замыслу». От команды ЭФ:

Примечание. Мы не поддерживаем использование нескольких классов конфигурации в одном AppDomain. Если вы используете этот атрибут для установки разных классов конфигурации для двух контекстов, будет выдано исключение.

Дополнительная информация здесь: Конфигурация на основе кода (Codeplex)

Вопрос:

Как нам двигаться дальше? Любая помощь будет принята с благодарностью! Есть ли более гибкий способ подключения конфигурации к контексту вместо AppDomain?

(Наши контекстные классы расположены в разных сборках. Мы попробовали атрибут DbConfigurationType, но проблема в самом EF)

Файлы конфигурации:

Конфигурация для обычного SQL-сервера

public class EfConfiguration : DbConfiguration
{
    public EfConfiguration()
    {
        SetProviderServices(
            SqlProviderServices.ProviderInvariantName, 
            SqlProviderServices.Instance);

        SetDefaultConnectionFactory(new SqlConnectionFactory());
    }
}

Конфигурация для SQL Server Compact Edition

public class EfCeConfiguration : DbConfiguration
{
    public EfCeConfiguration()
    {
        SetProviderServices(
            SqlCeProviderServices.ProviderInvariantName,
            SqlCeProviderServices.Instance);

        SetDefaultConnectionFactory(
            new SqlCeConnectionFactory(SqlCeProviderServices.ProviderInvariantName));
    }
}

ОБНОВЛЕНИЕ:

Ошибка, которую мы получаем:

System.TypeInitializationException : инициализатор типа для MyProject.Repositories.Base.DataContext вызвал исключение. ----> System.InvalidOperationException : был установлен экземпляр EfCeConfiguration, но этот тип не был обнаружен в той же сборке, что и контекст DataContext. Либо поместите тип DbConfiguration в ту же сборку, что и тип DbContext, либо используйте атрибут DbConfigurationTypeAttribute для типа DbContext, чтобы указать тип DbConfiguration, либо задайте тип DbConfiguration в файле конфигурации. См. http://go.microsoft.com/fwlink/?LinkId=260883. больше информации.

ОБНОВЛЕНИЕ 2, решение Как описано выше, у нас может быть только одна конфигурация. Это проблема, поскольку Sql и SqlCe используют разных поставщиков. Если мы используем «SetDefaultConnectionFactory» для соответствия одному типу базы данных, другой потерпит неудачу.

Вместо этого укажите соединение в контексте, как описано в сообщении, отмеченном как ответ ниже. Как только вы всегда инициализируете контекст соединением, а не строкой соединения, все готово. Вы можете удалить вызов SetDefaultConnectionFactory из конфигурации. Мы используем только приведенный ниже код для настройки контекста SqlCe и не используем конфигурацию для контекста Sql.

  public class CommonEfConfiguration : DbConfiguration
    {
        public CommonEfConfiguration()
        {
            // EF does not know if the ce provider by default,
            // therefore it is required to be informed about it.
            // The connection factories are not necessary since the connection
            // is always created in the UnitOfWork classes
            SetProviderServices(SqlCeProviderServices.ProviderInvariantName, SqlCeProviderServices.Instance);
        }
    }

person Henrik Carlsson    schedule 03.12.2013    source источник
comment
Я немного запутался - у меня есть две базы данных в двух отдельных проектах (сборках) С#, каждая со своей собственной конфигурацией, и у меня никогда не было никаких проблем.   -  person Kirk Woll    schedule 03.12.2013
comment
Кирк: Используете ли вы EF6 и выполняете ли вы их в одном и том же домене приложения? Мы используем nunit и проводим интеграционный тест в двух системах, но запускаем их как одну. Отлично работал в EF5, где не нужно было указывать провайдера в конфигурации.   -  person Henrik Carlsson    schedule 03.12.2013
comment
Да, и да. Какую реальную ошибку вы испытываете?   -  person Kirk Woll    schedule 03.12.2013
comment
@kirk Проблема с обнаружением DBConfiguration, если она используется. Возможно, в вашем сценарии есть все части в правильной сборке для автоматического обнаружения. Если используемые классы DBConfig находятся в одной сборке :-( становится неприятно   -  person phil soady    schedule 03.12.2013
comment
@kirk: вселяет в меня надежду, что вы решили эту проблему! :) Я разместил ошибку в обновлении в вопросе.   -  person Henrik Carlsson    schedule 03.12.2013
comment
@ Хенрик, разница в том, что моя конфигурация содержится в той же сборке, что и мой контекст данных. Есть ли причина, по которой вы не можете этого сделать?   -  person Kirk Woll    schedule 03.12.2013
comment
@Kirk, проблема решена! Проблема заключалась в том, что мы создавали DbContext со строками подключения, которые плохо сочетаются с singleton connectionFactory, когда вам нужны подключения к Sql и SqlCe. Вместо этого теперь мы создаем отправку DbContext в определенных соединениях. Теперь конфигурацию фабрик можно удалить.   -  person Henrik Carlsson    schedule 03.12.2013
comment
У меня точно такая же проблема, но между mssql и mysql. Я пытаюсь применить ваше решение, но MySqlEFConfiguration кажется другим   -  person Bastiflew    schedule 15.07.2014
comment
@Baptiste у вас как-то получилось, что у меня точно такая же проблема с mssql и mysql вместе?   -  person Hitendra    schedule 04.05.2017
comment
@Hitendra Это было давно, но я помню, что мне пришлось вернуться в EF5.   -  person Bastiflew    schedule 04.05.2017


Ответы (3)


РЕДАКТИРОВАТЬ: на основе сведений об ошибке: вы уже пытались сообщить EF, где находится класс конфигурации?

[DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssemblyFullyQualifiedName")]
public class MyContextContext : DbContext
{
}

Если это не работает, см. альтернативу

Используйте контекст с конструктором DbConnection

public class MYDbContext : DbContext {
     // MIgration parameterless constructor is managed in  MyMigrationsContextFactory 

    public MyDbContext(string connectionName) : base(connectionName) { } // no this

    public MYDbContext(DbConnection dbConnection, bool contextOwnsConnection)  // THIS ONE
        : base(dbConnection, contextOwnsConnection) {  }

затем вам нужно соединение "DBConnection" для каждого провайдера. Для SQL-сервера

      public DbConnection GetSqlConn4DbName(string dataSource, string dbName) {
        var sqlConnStringBuilder = new SqlConnectionStringBuilder();
        sqlConnStringBuilder.DataSource = String.IsNullOrEmpty(dataSource) ? DefaultDataSource : dataSource;
        sqlConnStringBuilder.IntegratedSecurity = true;
        sqlConnStringBuilder.MultipleActiveResultSets = true;

        var sqlConnFact = new SqlConnectionFactory(sqlConnStringBuilder.ConnectionString);
        var sqlConn = sqlConnFact.CreateConnection(dbName);
        return sqlConn;
    }

повторите для фабрики SqlCe, она также может генерировать DBConnection фактор соединения SqlCe создать соединение

person phil soady    schedule 03.12.2013
comment
Да, я пытался указать его для обоих файлов конфигурации. Это сообщение, которое я получил. - person Henrik Carlsson; 03.12.2013
comment
Спасибо чувак! У нас уже была концепция для CE-соединения, но для обычных соединений мы использовали строку соединения. Когда вместо этого мы предоставили соединение с контекстом, конфигурация больше не была нужна! (За исключением определения поставщика) - person Henrik Carlsson; 03.12.2013
comment
Вы можете упомянуть, что MyAssembly должно быть полным именем. - person quillbreaker; 24.12.2014
comment
@phil soady ты знаешь о оракуле? - person Amir; 04.11.2016
comment
Я никогда не использовал поставщика Oracle EF. Посетите их веб-сайт, чтобы узнать больше. oracle.com/technetwork/topics/ точка/загрузки/ - person phil soady; 05.11.2016
comment
Полезная ссылка для будущих зрителей. Объясняет, как настроить разделы. msdn.microsoft.com/en-us/data/jj680699 - person Pangamma; 19.11.2016

что я сделал:

public partial class MyDataBaseContext : DbContext
{
    public MyDataBaseContext (string ConnectionString)
        : base(ConnectionString)
    {
    }
}
person havalli    schedule 26.02.2014
comment
с чем-то вроде var ConnectionString = @"Data Source="C:\temp\mydatabase.sdf" это работает нормально. - person Mare Infinitus; 29.04.2015
comment
Из моего класса MVC HomeController я сделал следующее: общедоступная статическая строка только для чтения conStr = ConfigurationManager.ConnectionStrings[SudentConext].ToString(); MyDataBaseContext db = новый MyDataBaseContext (conStr); - person Dan Randolph; 12.04.2016

Я нашел решение в сообщение на форуме Microsoft.

По сути, у меня было два проекта, каждый со своим контекстом. Entity Framework загружал только (первый) один из классов DbConfiguration и пытался использовать одну и ту же конфигурацию для обоих проектов. Это причина сообщения об ошибке, говорящего что-то вроде

«Экземпляр EfCeConfiguration был установлен, но этот тип не был обнаружен в той же сборке, что и контекст DataContext».

Итак, как кто-то предложил на форуме сообщение на форуме Microsoft, я удалил все аннотации [DbConfigurationType(typeof(DbConfigurationClass))] из классов, наследуемых от DbContext, в обоих проектах, и ошибка больше не возникала.

person Ulysses Alves    schedule 21.03.2017
comment
Но побежал ли он после этого? Я имею в виду, что используемый вами подкласс DbConfiguration важен для правильной работы во время выполнения. Он настраивает множество специфичных для СУБД вещей (например, совершенно разные настройки для MySQL и MSSQL), такие как преобразователь зависимостей (например, MySqlDependencyResolver), фабрика провайдеров (например, MySqlClientFactory), службы провайдеров (например, MySqlProviderServices), фабрика соединений (например, MySqlConnectionFactory ), генератор миграции, преобразователь фабрики поставщика, преобразователь токена манифеста и контекст истории. Вы не можете просто не указывать все это и заставить это работать. - person Triynko; 17.04.2019
comment
Я не знаю, братан. Я не помню подробностей проекта, над которым я работал, когда ответил на него, но я уверен, что в то время он решил проблему. Теперь, чтобы проверить то, на что вы указываете, я думаю, вам будет лучше проверить это, потому что у меня больше нет среды, в которой эта проблема возникает. - person Ulysses Alves; 17.04.2019