Попытка перехода с Entity Framework 5 на 6 или DataBase-First = Code-First + браузер диаграммы

в 7:40, , рубрики: .net, entity framework, метки: ,

Хочу поделиться граблями перехода с EFW 5 на 6 в случае DataBase-First.

Тесно работаю с Entity Framework с пелёнок. Пересел на него с Linq2SQL.
Особых проблем с переходами между версиями не встречал. И в целом — каждый переход оправдывал ожидания.
Но сегодня я был слегка разочарован.

На старте у меня есть 6 штук DataBase-First репозиториев, раскиданных по солюшену VS 2012 на .NET 4.5. И я их попытался перевести на EFW 6.

Итак, что нужно делать и в каком порядке.

1. Зайти в менеджер NuGet (Manage NuGet Packages), открыть вкладку Updates и установить Entity Framework 6 (6.0.1)
Эта процедура удалит ссылки на старые сборки и добавит две новые сборки в проект (EntityFramework.dll, EntityFramework.SqlServer.dll)
Это нужно сделать для каждого проекта, где есть EFW. Если всё это в итоге запускается где-то в другом приложении — то там необходимо внести аналогичные изменения в app.config (web.config)

2. У вас в проекте появится масса ошибок компиляции. Но не спешите их исправлять. Сначала мы заменим генератор сущностей и, тем самым, автоматически исправим часть ошибок. Если в проекте уже использовались генераторы — удаляем (ищем и удаляем *.tt)
Идем в просмотр диаграммы, жмем правую педаль и выбираем «Add Code Generation Item» и выбираем «EF 6.x DBContextGenerator».
Если у вас установлена VS 2012 (а не 2013), то предварительно нужно установить Entity Framework Tools 6

3. Теперь исправляем ошибки компиляции.
Как правило, ошибки связаны с тем, что изменились namespace.
Шаблон изменений в большинстве случаев такой: после System.Data добавляется .Entity.Core.

Всё, проект готов к запуску.

А теперь о граблях.

1. Пропало (перенесено) куча методов, которые не исправить в коде автоматически.
Например:
Context.DeleteObject() больше нет, теперь иди в нужный DbSet и вызывай Remove() там.

context.Delete(user); //было
context.Users.Remove(user); //стало

Context.AddTo*** тоже теперь нет, иди в нужный DbSet и вызывай Add() там.

context.AddToUsers(user); //было
context.Users.Add(user); //стало

Метода DbSet.AddObject тоже не стало, но тут можно решить автозаменой [AddObject] => [Add]
Особо продвинутые могут написать Extension.

2. Изменились внутренние типы.
Если раньше context.Connection был типа EntityConnection
То теперь там вдруг оказался SqlConnection.
Что поломало часть моего кода (смысл кода был — в «узких» местах узнать строку соединения и на ADO.Net сделать нужные вещи)

3. Вообще пропали события у контекста.
Т.е. теперь context.SavingChanges события просто нет.

4. Классы, которые генерируются теперь не обладают былой функциональностью. Я бы сказал, что они теперь от структур вообще не отличаются.
Они даже не наследуются от EntityObject.

5. Было два репозитория, основанных на разных БД. В них присутствовали таблицы с одинаковыми именами. В итоге в репозиториях были классы с одинаковыми именами, но разными пространствами имен. На Entity Framework 5 это не создавало проблем. А вот на 6-ке код скомпилировался, но в runtime я поймал exception, что-то про невозможность разрешения имени (в сообщении фигурировали эти самые классы из разных пространств имен)

Пункты 3 и 4 наводят меня на мысль, что DataBase-First подход был слит. Остался лишь Code-First + ширма в виде браузера диаграммы классов.

Ну и фаталити — после перехода на 6.0.1 мой код стал работать медленнее.
Возможно, дело в том, что стали генерироваться другие, более оптимальные запросы и они пошли мимо индексов, созданных для EFW 5.
Но разбираться в причинах я уже не стал. Просто отложил переход на более свободное время.

Автор: Sioln

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js