2010-10-26 18 views
14

Esto es puramente una idea conceptual y de diseño relacionada con EF4.Modificación de un modelo de marco de entidad en tiempo de ejecución

El ejemplo/escenario es un gran sistema de tipo ERP o CRM en el que las empresas pueden necesitar agregar "campos definidos por el usuario" tradicionales para capturar datos adicionales.

Sé que el EF tiene algunas capacidades para enviar el modelo a una base de datos en tiempo de ejecución, pero la pregunta es ¿puede usar EF para modificar un modelo y actualizar el almacén de datos en tiempo real?

En otras palabras, si proporciono al usuario un mecanismo para agregar una columna definida por el usuario, el tipo de datos asociado y los requisitos nulos se pueden hacer sobre la marcha con EF y luego recordar para todas las sesiones futuras?

Está por ahí, pero creo que todos verán a qué me refiero.

Brent

+0

¿Terminaste con la solución? – Guillaume

+0

No lo hice. Nunca pude probar o hacer que algo funcione. Terminé yendo con código primero a la larga de todos modos. –

Respuesta

14

Me han hecho esta pregunta algunas veces en el pasado. No hay una manera obvia o fácil. Es posible que no haya forma, pero somos desarrolladores y siempre hay una forma. ¿Sé lo que es eso? No. ¿Puedo soñar algunas ideas? .... Mmmm .. en tiempo de ejecución, el modelo se basa en clases fuertemente tipadas del metadataworkspace. Puedes crear esos sobre la marcha. Pero luego necesita modificar el xml del archivo edmx. Hay LINQ a XML o xpath para eso. Modificando el esquema de la base de datos ... cómo el modelo primero crea dbs ... crea sql y luego lo ejecuta. Tendría que crear sql (cómo? Shrug) y ejecutarlo (objectcontext.executestorecommand()). ¿Factible? ¿Posible? No tengo ni idea. Realmente, la respuesta es no ... no hay nada en VS o .NET 4 (API de EF) que permita habilitar esto hasta donde yo sé. Seguramente alguien más inteligente y paciente de lo que me gasté (¿desperdicia?) Mucho tiempo (tratando de) ser más astuto que EF para lograrlo. Sin embargo, basado en su respuesta a la sugerencia de la publicación de blog de Jeremy, usted está buscando algo integrado/útil. Eso es más fácil de responder con un "nope".

Julie

+7

¡Bienvenido a SO, Julie! – Yakimych

+0

Estoy pensando que una combinación de código primero con 'ExpandoObject' podría hacerlo. Pero en lugar de reificar los campos definidos por el usuario, tiene más sentido para mí tratarlos como no estándar de todos modos. +1 a Yakimych; ¡Bienvenido! –

+0

Estoy de acuerdo en que sería mucho más fácil con el código primero y sin ningún modelo, una capa menos de complejidad y reglas para manejarlo. Pero aún así, mucho trabajo –

1

Jeremy Miller analiza un conjunto similar en this article. Está usando nHibernate, pero podría darte algunas ideas.

+0

Sí, me da algunas ideas, ninguna de las cuales es simple. Me sorprende que este requisito no sea común con nHibernate o EF para ese asunto. ¿Algún otro recurso o idea? Realmente no respondí la pregunta que acaba de proporcionar una referencia, es difícil cerrar la pregunta para eso. –

+0

pensé en hacerlo, pero mi escenario significa que tengo que permitir que el usuario agregue "empleado" en primer lugar antes de definir los campos personalizados ... en cierto sentido, incluso la tabla es personalizada. – War

11

Hay a menudo más de una manera de resolver un problema, y ​​esto no es una excepción. En este caso, lo que está buscando es permitir a los usuarios agregar nuevos campos a su aplicación y base de datos y usar esos campos desde su aplicación. Algunas formas de hacerlo son:

a) Permitir a los usuarios modificar el esquema de la base de datos.
b) Cree una estructura separada para definir 'campos definidos por el usuario' y almacenar datos en ellos.
c) Cree campos 'reservables' que aceptan nulos en las tablas donde es más probable que los usuarios necesiten sus propios campos.

Prefiero el enfoque (b) y, a veces el enfoque (c) siempre que se necesiten campos personalizados definidos por el usuario en una aplicación. Estas son algunas de las ventajas/desventajas de cada uno de los tres:

Modificar esquema

arriesgado: Si permite que los usuarios modifiquen el esquema de base de datos, ¿dónde trazar la línea? Si pueden agregar campos, también pueden cambiar la definición de los campos existentes, agregar o eliminar índices, etc. Esto puede llevar a una pesadilla de soporte con errores, problemas de rendimiento, etc. provocados por las modificaciones de esquema realizadas por los usuarios.
Performant: el almacenamiento de los nuevos campos definidos por el usuario en línea en las tablas existentes generalmente tendrá una ventaja de rendimiento sobre una estructura separada, pero solo mientras no vaya por la borda con los cambios.
Clunky: EF determina el esquema en tiempo de diseño, por lo que para que esto funcione en tiempo de ejecución necesitará generar nuevas clases de entidad en tiempo de ejecución con miembros que representen los nuevos campos, y deberá actualizar los metadatos de asignación en tiempo de ejecución Las clases de entidad generadas en tiempo de ejecución pueden heredar de las clases generadas en tiempo de diseño, por lo que solo necesita agregar miembros y asignaciones para los nuevos campos definidos por el usuario. Aunque es posible, es torpe. El código que consume las clases generadas en tiempo de ejecución necesitará usar la reflexión para acceder a los nuevos miembros que se crean en tiempo de ejecución.

estructura independiente

Fácil de usar: Mediante la creación de una estructura separada para almacenar campos personalizados, se puede construir la lógica de aplicación para los usuarios añadir/eliminar aquellos campos, etc. Ellos no necesitan meterse con la base de datos, en su lugar puede tener formularios de mantenimiento dentro de la aplicación para agregar nuevos campos.
compatible con EF: no hay necesidad de meterse con las clases de entidad y los metadatos de asignación en tiempo de ejecución. Todo está definido en tiempo de diseño, y los campos definidos por el usuario son solo datos.
Un poco menos rendimiento: Tener tablas separadas para definir y almacenar los campos definidos por el usuario puede hacer que las búsquedas sean ligeramente más costosas debido a viajes de ida y vuelta adicionales o uniones adicionales.

Separate table structure for user defined fields

Campos reservados

suficiente frecuencia: En muchas situaciones, los campos personalizados sólo se utilizan para uno o unos campos adicionales. Reservar un par de columnas a menudo cubrirá el 99% de las necesidades del usuario. Incluso un campo genérico de "comentarios" en cada tabla suele ser suficiente en las aplicaciones LOB.
Limited: Si los usuarios quieren más campos de los que ha reservado u otros tipos de datos que los reservados, eso puede ser una limitación.
Performant: Columnas en línea, recuperadas sin vueltas ni combinaciones adicionales.
Definido en tiempo de diseño: Sin tiempo de ejecución jugando con definiciones de tipos de entidades o asignaciones.

Reserved fields

2

Brent me hace ping en Twitter hoy (casi 2 años después de este post) para ver si algo ha cambiado. Este escenario aún no es compatible con EF. Sin embargo, Rowan Miller tiene una publicación interesante sobre cómo llevar esto a cabo con Code First http://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/

Esto puede o no hacer lo que necesita, pero vale la pena echarle un vistazo.

0

Esta es una versión de Reserved fields de @KristoferA respuesta que he utilizado en el pasado.

Puede agregar una columna XML (o JSON) adicional en cada tabla que probablemente requiera datos personalizados y luego leerla/escribirla desde db usando EF.Después de leer deserializar XML (JSON) y pasarlo al mecanismo que se supone que maneja las asignaciones, presentarlo al usuario. Lo mismo ocurre con la escritura de datos que se leen desde la interfaz de usuario -> asignar a objeto -> serializar a XML (JSON) -> y escribir en estos campos adicionales.

Cuestiones relacionadas