Modelado de asociaciones polimórficas base de datos primero frente a código primero

Tenemos una base de datos en la que una tabla contiene registros que pueden ser secundarios a otras tablas. Tiene una clave externa "blanda" que consta de la identificación del propietario y un nombre de tabla. Este (anti) patrón se conoce como "asociaciones polimórficas". Sabemos que no es el mejor diseño de base de datos y lo cambiaremos a su debido tiempo, pero no en el futuro cercano. Déjame mostrarte un ejemplo simplificado:

AmbosEvent, PersonyProduct tener registros en el comentario. Como ves, no hay restricciones FK duras.

En Entity Framework es posible admitir este modelo mediante la sublasificaciónComment dentroEventComment etc. y dejarEvent tienen unaEventComments colección, etc .:

Las subclases y las asociaciones se agregan manualmente después de generar el modelo básico de la base de datos.OwnerCode es el discriminador en estoTPH modelo. Tenga en cuenta queEvent, PersonyProduct Son entidades completamente diferentes. No tiene sentido tener una clase base común para ellos.

Esta es la base de datos primero Nuestro modelo de la vida real funciona así, no hay problema.

DE ACUERDO. Ahora queremos pasar al código primero. Así que empecé a aplicar ingeniería inversa de la base de datos en un modelo de código primero (EF Power Tools) y continué creando las subclases y mapeando las asociaciones y la herencia. Intenté conectar al modelo en Linqpad. Fue entonces cuando empezaron los problemas.

Cuando se intenta ejecutar una consulta con este modelo, se lanza unInvalidOperationExeception

El componente de clave foránea 'OwnerId' no es una propiedad declarada en el tipo 'EventComment'. Verifique que no se haya excluido explícitamente del modelo y que sea una propiedad primitiva válida.

Esto sucede cuando tengo asociaciones bidireccionales yOwnerId se mapea como una propiedad enComment. El mapeo en miEventMap clase (EntityTypeConfiguration<Event>) Se ve como esto:

this.HasMany(x => x.Comments).WithRequired(c => c.Event)
    .HasForeignKey(c => c.OwnerId);

Así que traté de mapear la asociación sinOwnerId en el modelo:

this.HasMany(x => x.Comments).WithRequired().Map(m => m.MapKey("OwnerId"));

Esto arroja unMetaDataException

El esquema especificado no es válido. Errores: (10,6): error 0019: cada nombre de propiedad en un tipo debe ser único. El nombre de propiedad 'OwnerId' ya estaba definido. (11,6): error 0019: cada nombre de propiedad en un tipo debe ser único. El nombre de propiedad 'OwnerId' ya estaba definido.

Si elimino dos de las tres asociaciones de comentarios de entidades, está bien, pero por supuesto eso no es una cura.

Algunos detalles adicionales:

Es posible crear un modelo DbContext que funcione ("segundo código") a partir de edmx agregando un elemento del generador DbContext. (Esto sería una solución temporal por el momento).Cuando exporto el modelo de código primero de trabajo (con una asociación) a edmx (EdmxWriter) la asociación parece estar en el modelo de almacenamiento, mientras que en el edmx original forman parte del modelo conceptual.

Entonces, ¿cómo puedo crear este código de modelo primero? Creo que la clave es cómo indicar al código primero que mapee las asociaciones en el modelo conceptual, no en el modelo de almacenamiento.

Respuestas a la pregunta(1)

Su respuesta a la pregunta