Изменение модели платформы Entity во время выполнения
Это чисто концептуальная и дизайнерская идея, связанная с EF4.
Пример/сценарий - это большая система типов ERP или CRM, где компаниям может потребоваться добавить традиционные "пользовательские поля" для сбора дополнительных данных.
Я знаю, что EF имеет некоторые возможности выталкивать модель в базу данных во время выполнения, но на самом деле вопрос: можете ли вы использовать EF для модификации модели и обновления хранилища данных в режиме реального времени?
Другими словами, если я предоставляю пользователю механизм для добавления определенного пользователем столбца, соответствующий тип данных и нулевые требования могут выполняться "на лету" с помощью EF, а затем запоминаются для всех будущих сеансов?
Это там, но я думаю, вы все увидите, что я получаю.
Брент
Ответы
Ответ 1
Мне задавали этот вопрос несколько раз в прошлом. Нет очевидного или простого способа. Возможно, что нет способа, но мы разработчики, и всегда есть путь! Знаю ли я, что это? Нет. Могу ли я придумать некоторые идеи?.... Mmmm.. во время выполнения модель основана на строго типизированных классах из метаданных. Вы можете создавать их на лету. Но тогда вам нужно изменить xml файла edmx. Для этого LINQ to XML или xpath. Модификация схемы базы данных... как первая модель построит dbs... она создает sql, а затем вы ее выполняете. Вам нужно будет создать sql (как? Shrug) и выполнить его (objectcontext.executestorecommand()). Реализуемое? Возможное? Я понятия не имею. На самом деле ответ - нет... нет ничего в VS или .NET 4 (API EF), чтобы легко включить это, насколько я знаю. Конечно, кто-то более умный и терпеливый, чем я был потрачен (потрачен впустую??) много времени (пытается) перехитрить EF, чтобы снять это. Основываясь, однако, на вашем ответе t на предложение re Jeremy blog post, вы ищете что-то встроенное/удобное. Это легче ответить "нет".
Julie
Ответ 2
Часто бывает несколько способов решить проблему, и это не исключение. В этом случае то, что вы ищете, позволяет пользователям добавлять новые поля в ваше приложение и базу данных и использовать эти поля из вашего приложения. Некоторые способы сделать это:
a) Разрешить пользователям изменять схему базы данных.
b) Создайте отдельную структуру для определения "пользовательских полей" и хранения данных в них.
c) Создайте поля с нулевым значением "зарезервированные" в таблицах, где пользователям больше понадобятся собственные поля.
Я предпочитаю подход (b), а иногда и (c) подход, когда пользовательские поля, определенные пользователем, необходимы в приложении. Вот некоторые из плюсов/минусов для каждого из трех:
Изменить схему
• Рискованный. Если вы разрешаете пользователям изменять схему базы данных, где вы рисуете линию? Если они могут добавлять поля, они также могут перестать изменять определение существующих полей, добавлять или удалять индексы и т.д. Это может привести к кошмару поддержки с ошибками, проблемами производительности и т.д., Вызванными изменениями схемы, сделанными пользователями.
• Performant: сохранение новых пользовательских полей inline в существующих таблицах обычно будет иметь преимущество производительности над отдельной структурой, но только до тех пор, пока они не перейдут за борт с изменениями.
• Clunky: EF определяет схему во время разработки, поэтому для выполнения этой работы во время выполнения вам потребуется создать новые классы сущностей во время выполнения с членами, представляющими новые поля, и вам потребуется обновить метаданные сопоставления во время выполнения. Сгенерированные во время выполнения классы сущностей могут наследоваться от классов, сгенерированных по времени разработки, поэтому вам нужно только добавлять элементы и сопоставления для новых пользовательских полей. Хотя это возможно, он неуклюж. Код, который потребляет классы, генерируемые во время выполнения, должен будет использовать отражение для доступа к новым членам, созданным во время выполнения.
Отдельная структура
• Удобный для пользователя: создавая отдельную структуру для хранения настраиваемых полей, вы можете создавать логику приложений для пользователей, чтобы добавлять/удалять эти поля и т.д. Им не нужно связываться с базой данных, вместо этого вы можете иметь формы обслуживания в приложении для добавления новых полей.
• EF-friendly: нет необходимости возиться с классами сущностей и отображать метаданные во время выполнения. Все определяется во время разработки, а определяемые пользователем поля - это просто данные.
• Немного менее результативны: наличие отдельных таблиц для определения и хранения пользовательских полей может сделать поиск немного более дорогостоящим из-за дополнительных обращений или дополнительных объединений.
![Separate table structure for user defined fields]()
Зарезервированные поля
• Достаточно часто: во многих ситуациях пользовательские поля используются только для одного или нескольких дополнительных полей. Сохранение нескольких столбцов часто охватывает 99% потребностей пользователей. Даже общее поле "примечаний" в каждой таблице часто бывает достаточно для приложений LOB.
• Ограничено: если пользователям требуется больше полей, чем вы зарезервировали, или другие типы данных, чем вы зарезервировали, это может быть ограничение.
• Performant: Columns inline, извлекается без дополнительных обращений или соединений.
• Определено во время разработки: без использования времени выполнения с определениями сущностей или сопоставлениями.
![Reserved fields]()
Ответ 3
Брент пинговал меня в Twitter сегодня (почти через 2 года после этого сообщения), чтобы узнать, изменилось ли что-то. Этот сценарий по-прежнему не поддерживается EF. Однако у Роуэн Миллер есть интересный пост о том, как это сделать с помощью Code First http://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/
Это может или не может делать то, что вам нужно, но стоит посмотреть.
Ответ 4
Джереми Миллер обсуждает аналогичную настройку в в этой статье. Он использует nHibernate, но может дать вам некоторые идеи.
Ответ 5
Это версия Reserved fields
из ответа @KristoferA, которую я использовал в прошлом.
Вы можете добавить один дополнительный столбец XML (или JSON) для каждой таблицы, который может потребовать пользовательские данные, а затем прочитать/записать его из db с помощью EF
. После чтения десериализовать XML (JSON) и передать его механизму, который должен обрабатывать сопоставления, затем представить его пользователю. То же самое касается записи данных, которые вы читаете из UI → map to object → serialize to XML (JSON) → и записи в эти дополнительные поля.