UnintentionalCodeFirstException | Модульное тестирование Entity Framework с Effort.Ef6 с использованием Database First

Ситуация

Я хочу включить модульное тестирование моего DbContext на основе Entity Framework 6. Я создал свою DbContext и свои модели с первым подходом к базе данных, и теперь у меня есть файл конструктора .edmx.

Эта проблема

Мой автоматически созданный DbContext переопределяет DbContext.OnModelCreating такой метод:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    throw new UnintentionalCodeFirstException();
}

Я пытаюсь создать новый экземпляр моего DbContext в моей ложной службе доступа к данным на основе информации этой статьи. Мой код не сталкивается с Database.SetInitializer;, как указал автор этого сообщения в блоге. Мой конструктор выглядит точно так же, как его. Моя инициализация DbContext выглядит так:

public DatabaseEntities(DbConnection connection) 
     : base(connection, true) { }

Что приводит к следующему исключению при достижении ранее упомянутого переопределенного OnModelCreating

System.Data.Entity.Infrastructure.UnintentionalCodeFirstException: 'Контекст используется в режиме Code First с кодом, созданным из файла EDMX для разработки Database First или Model First. Это не будет работать правильно. Чтобы устранить эту проблему, не удаляйте строку кода, вызывающую это исключение. Если вы хотите использовать Database First или Model First, убедитесь, что строка подключения Entity Framework включена в app.config или web.config запускаемого проекта. Если вы создаете свой собственный DbConnection, убедитесь, что это EntityConnection, а не какой-либо другой тип DbConnection, и что вы передаете его одному из базовых конструкторов DbContext, которые принимают DbConnection. Чтобы узнать больше о Code First, Database First и Model First, см. документацию по Entity Framework здесь: http://go.microsoft.com/fwlink/?LinkId=394715'

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

Что я уже пытался сделать

  • Долго искал решение в интернете.
  • Раскомментируйте переопределенный OnModelCreating().
  • Я уже безуспешно пытался применить это решение.
  • Смоделируйте мой DbContext с помощью Moq, что определенно не вариант.

Вопрос

Как я могу создать и использовать базу данных в памяти (с усилием)?


Дополнительная информация

Когда я раскомментирую OnModelCreating(), при первом доступе к DataContext будет выдано исключение. Например.:

DbConnection effortConnection = Effort.DbConnectionFactory.CreatePersistent("MockedDatabaseEntities");

using (DatabaseEntities dataContext = new DatabaseEntities(effortConnection))
{
    dataContext.Students.Count(); // Exception throws here
}

System.Data.Entity.ModelConfiguration.ModelValidationException: 'Во время создания модели обнаружена одна или несколько ошибок проверки: MyApplication.Shared.Model.KeyValuePair: : EntityType 'KeyValuePair' не имеет определенного ключа. Определите ключ для этого EntityType. KeyValuePairs: EntityType: EntitySet «KeyValuePairs» основан на типе «KeyValuePair», для которого не определены ключи.


person WΩLLE - ˈvɔlə    schedule 12.09.2017    source источник
comment
В чем проблема, когда OnModelCreating был раскомментирован (потому что нам нужно как-то избавиться от этого)? Если он просто воссоздается каждый раз, когда вы строите свою модель, вы можете просто создать подкласс DatabaseEntities и еще раз переопределить его чем-то, что не взрывается.   -  person Robert Jørgensgaard Engdahl    schedule 12.09.2017
comment
На заметку; если вы используете Effort с базами данных pr test в памяти (переходными), ownsDbConnection во время теста должен иметь значение false (логический параметр для вашего базового конструктора).   -  person Robert Jørgensgaard Engdahl    schedule 12.09.2017
comment
Если ничего не помогает, я работаю в среде db-first, но я вручную сопоставил объекты с таблицами SQL.   -  person Robert Jørgensgaard Engdahl    schedule 12.09.2017
comment
@RobertJørgensgaardEngdahl - я обновил свой вопрос. Заранее спасибо!   -  person WΩLLE - ˈvɔlə    schedule 12.09.2017
comment
У вас есть первичный ключ для вашей таблицы KeyValuePair?   -  person Robert Jørgensgaard Engdahl    schedule 12.09.2017
comment
@RobertJørgensgaardEngdahl - Да, первичный ключ существует. Но это не uniqueidentifier, как во всех других таблицах. Его тип nchar(50)   -  person WΩLLE - ˈvɔlə    schedule 12.09.2017
comment
Из-за ошибки EntityType 'KeyValuePair' ключ не определен, вы должны каким-то образом указать EntityFramework, что у вас есть ключ. Вы можете сделать это в OnModelCreating, как это сделано здесь stackoverflow.com/a/13612347/2154774   -  person Robert Jørgensgaard Engdahl    schedule 12.09.2017


Ответы (2)


Если кто-то ищет решение для подхода db-first, это сработало для меня:

string connStr = @"metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;";
DbConnection connection = EntityConnectionFactory.CreateTransient(connStr);
return new MyDatabaseContext(connection);

Я получил часть connStr из моего web/app.config.
Кроме того, я не трогал OnModelCreating.

person Károly Ozsvárt    schedule 27.04.2020

Проблема заключалась в том, что мне нужно было указать ключ для моего набора данных KeyValuePair.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<KeyValuePair>().HasKey(x => x.Key);
    base.OnModelCreating(modelBuilder, null);
}

Большое спасибо Роберт Йоргенсгаард Энгдал!

person WΩLLE - ˈvɔlə    schedule 12.09.2017