Есть группа сервисов, работающих с одной и той же базой. Доступ к базе идёт через Linq2Sql и через Entity Framework (разные сервисы, написанные в разное время и разными командами). Со всем этим зоопарком всплывает одна общая проблема — при любом изменении схемы базы данных все эти фреймворки отваливаются.
Я сейчас хочу привести всё это в порядок, унифицировать доступ к базе и, среди прочего, мне нужно предложить какое-то нормальное решение для изменений схемы данных. "Нормальным" в моём понимании будет решение, которое позволит изменять структуру таблиц так, чтоб сервисы, работающие с этими таблицами, не отваливались.
Со стороны самой базы данных всё более-менее понятно — если мы удаляем столбец, то естественно всё развалится. Поэтому удалять столбцы мы будем только после того как столбец удалён из всех linq2sql / EF маппингов. Тут другое. Как сделать чтобы при добавлении столбцов оно не вываливалось с эксепшном о несовпадении схемы?
У меня есть кое-какие мысли о перенаправлении запросов чтения на View вместо самих таблиц, но тогда придётся поддерживать какую-то версионность этих view.. Да и вопрос со вставкой данных остаётся. Другой мысль — обернуть всё в хранимые процедуры, но тогда нужна будет версионность этих процедур..
Мне думается, что этой задачей люди занимались ещё много лет назад и наверняка есть какие-то готовые решения и рекоммендации для Entity Framework или Linq2Sql чтобы избегать таких эксепшнов.
Подскажите, куда стоит копнуть?..
С уважением, Artem Korneev.
Re: Изменение базы с Linq2Sql или Entity Framework
Здравствуйте, Artem Korneev, Вы писали:
AK>Со стороны самой базы данных всё более-менее понятно — если мы удаляем столбец, то естественно всё развалится. Поэтому удалять столбцы мы будем только после того как столбец удалён из всех linq2sql / EF маппингов. Тут другое. Как сделать чтобы при добавлении столбцов оно не вываливалось с эксепшном о несовпадении схемы?
Просто, при добавлении столбца задавайте ему default значение. У EF никаких проблем с новыми колонками нет.
AK>Мне думается, что этой задачей люди занимались ещё много лет назад и наверняка есть какие-то готовые решения и рекоммендации для Entity Framework или Linq2Sql чтобы избегать таких эксепшнов.
Просто явно перечисляте нужные столбцы без всяких * — уже много лет люди добавляют новые колонки в существующие базы и ничего не отваливается.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[2]: Изменение базы с Linq2Sql или Entity Framework
Здравствуйте, TK, Вы писали:
TK>Просто, при добавлении столбца задавайте ему default значение. У EF никаких проблем с новыми колонками нет.
Я только начал заниматься проблемой, примеров пока привести не могу. Но вот сегодня "Code First" EF отвалился на SELECT запросе с вот таким сообщением:
"ExceptionMessage": "The model backing the 'TenantAdminDbContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).",
Не знаю, специфично ли это для Code First или нет, но проблема явно есть. Я бегло просмотрел список изменений за последнюю неделю и пока не вижу ни одного удаления колонок. Только добавление новых таблиц (даже не колонок).
AK>>Мне думается, что этой задачей люди занимались ещё много лет назад и наверняка есть какие-то готовые решения и рекоммендации для Entity Framework или Linq2Sql чтобы избегать таких эксепшнов. TK>Просто явно перечисляте нужные столбцы без всяких * — уже много лет люди добавляют новые колонки в существующие базы и ничего не отваливается.
Ну столбцы перечисляют, когда запросы вручную пишут. Я же хочу использовать маппинги из Linq2Sql/EF, т.е. читать сразу объекты. Даже если оно там внутри отправляет *, то падать-то, в теории, не должно — старые столбцы никуда не делись, просто новые появились. А на практике — падает. Причём, как Linq2Sql, так и EF (Code First).
С уважением, Artem Korneev.
Re[3]: Изменение базы с Linq2Sql или Entity Framework
Здравствуйте, Artem Korneev, Вы писали:
AK>Я только начал заниматься проблемой, примеров пока привести не могу. Но вот сегодня "Code First" EF отвалился на SELECT запросе с вот таким сообщением:
AK>
"ExceptionMessage": "The model backing the 'TenantAdminDbContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).",
AK>Не знаю, специфично ли это для Code First или нет, но проблема явно есть. Я бегло просмотрел список изменений за последнюю неделю и пока не вижу ни одного удаления колонок. Только добавление новых таблиц (даже не колонок).
Естественно специфично. Просто отключите любые миграции — добавляйте маппинги руками.
AK>Ну столбцы перечисляют, когда запросы вручную пишут. Я же хочу использовать маппинги из Linq2Sql/EF, т.е. читать сразу объекты. Даже если оно там внутри отправляет *, то падать-то, в теории, не должно — старые столбцы никуда не делись, просто новые появились. А на практике — падает. Причём, как Linq2Sql, так и EF (Code First).
CodeFirst в данном случае значит то, что значит. Любые изменения надо вносить в код и только потом они попадают в бд
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[4]: Изменение базы с Linq2Sql или Entity Framework
Здравствуйте, TK, Вы писали:
TK>CodeFirst в данном случае значит то, что значит. Любые изменения надо вносить в код и только потом они попадают в бд
Дык оно так и было. Изменения внесли через код. Перезапустили один сервис — все остальные сервисы отвалились.
Для варианта CodeFirst есть какие-нибудь способы, не требующие точного совпадения схемы в коде и схемы в базе?
С уважением, Artem Korneev.
Re: Изменение базы с Linq2Sql или Entity Framework
Здравствуйте, Artem Korneev, Вы писали:
AK> Со всем этим зоопарком всплывает одна общая проблема — при любом изменении схемы базы данных все эти фреймворки отваливаются.
Ну это как бы нормально — ведь это два разных мира — C# и SQL. Обновил базу — перегенерил классы. Возможно, есть тулзы наоборот — по классам модифицировать базу. Но это уже сложнее, ибо система типов SQL более бестолкова и разрозненна. Да и неизвестно, куда мэпить String — в varchar, Nvarchar, NText, с какими лимитами, коллэйшенами и т.п.
AK>Подскажите, куда стоит копнуть?..
Да тут некуда копать — кругом ручная работа. Проще всего — в каком-нть билд-скрипте генерить классы по базе и сравнивать с эталонными.
Re[5]: Изменение базы с Linq2Sql или Entity Framework
Здравствуйте, Artem Korneev, Вы писали:
AK>Здравствуйте, TK, Вы писали:
TK>>CodeFirst в данном случае значит то, что значит. Любые изменения надо вносить в код и только потом они попадают в бд
AK>Дык оно так и было. Изменения внесли через код. Перезапустили один сервис — все остальные сервисы отвалились. AK>Для варианта CodeFirst есть какие-нибудь способы, не требующие точного совпадения схемы в коде и схемы в базе?
Database.SetInitializer<userstoredbContext>(null);
Инициализатор или значение NULL используются для отключения инициализации для данного типа контекста.