entity-framework - many - fluent api entity framework core
Reutilización de una columna para una propiedad requerida con Entity Framework 6.0, Fluent API y DataAnnotations (2)
Al presentar otro tipo, que contiene la propiedad requerida compartida por los otros dos, se logra lo que está buscando. Las entidades luego miran esto:
public class BaseClass
{
public int Id { get; set; }
}
public abstract class BaseIntermediaryClass : BaseClass
{
[Required]
public int Whatever { get; set; }
}
public class Foobar : BaseIntermediaryClass
{
}
public class Snafu : BaseIntermediaryClass
{
}
Y las asignaciones como esta:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BaseIntermediaryClass>().Property(fb => fb.Whatever).HasColumnName("Whatever");
base.OnModelCreating(modelBuilder);
}
El código completo del ejemplo de trabajo se puede encontrar aquí: https://gist.github.com/trayburn/7923392
Tengo una clase base
public class BaseClass
{
public int Id {get; set;}
}
y dos clases derivadas
public class Foobar: BaseClass
{
[Required]
public int Whatever {get; set;}
}
public class Snafu: BaseClass
{
[Required]
public int Whatever {get; set;}
}
Estoy usando la herencia Table Per Hierarchy y tratando de reducir mis columnas duplicadas, por lo que con Fluent API los he asignado de la siguiente manera:
modelBuilder.Entity<Foobar>().Property(fb => fb.Whatever).HasColumnName("Whatever");
modelBuilder.Entity<Snafu>().Property(sf => sf.Whatever).HasColumnName("Whatever");
Sin embargo, esto da como resultado
(137,10): error 3023: Problema en el mapeo de fragmentos comenzando en la línea 137: Columna BaseClass.Whatever en la tabla BaseClass debe estar mapeada: No tiene valor predeterminado y no puede contener nulos.
En EF6, este tipo de mapeo parece funcionar bien si elimino el atributo [Required]
de ambas subclases. Agregar un [DefaultValue(0)]
a ambas clases derivadas no soluciona el problema.
¿Alguna idea de cómo lograr que estas propiedades compartan una columna en la base de datos mientras mantienen su atributo requerido?
Esto es realmente un error en EF6. En EF5, el escenario solía no funcionar en absoluto (arrojaríamos una excepción en las líneas de "los nombres de columna deben ser únicos"). Mientras estuvimos en EF6 hicimos algo de trabajo para habilitarlo, pero aparentemente nos perdemos el hecho de que la columna compartida tiene que ser anulable en la base de datos, incluso si la propiedad es requerida en los tipos derivados. Lo último es que a menos que la clase base sea abstracta, debe poder almacenar una instancia del tipo base y para cualquier instancia del tipo base, la columna debe ser nula.
He archivado el problema en nuestra base de datos de errores:
https://entityframework.codeplex.com/workitem/1924
Siéntase libre de votar por ello.
En cuanto a una solución alternativa, si tener un tipo de intermediario no es una opción, puede marcar la columna como anulable adjuntando explícitamente una llamada a .IsOptional () en las configuraciones de entidad. Esto no le proporcionará exactamente lo que desea porque, a los efectos de la validación de datos EF, esta llamada a IsOptional () en la API fluida anulará la anotación de datos [Obligatorio]. Sin embargo, otros sabores de la validación de datos, como la validación de MVC, seguirán cumpliendo el atributo.
Hay otras soluciones posibles que no he probado, tal vez si es aceptable usar TPT y tener ambos tipos derivados. Lo que sea que viva en una mesa diferente esto funcionaría. Creo que cualquier enfoque que dependa de establecer un valor predeterminado no ayudará porque el error no se trata solo de que el esquema de la tabla no sea capaz de contener una instancia de la clase base, sino que también se trata de la asignación de EF generada por Code First. válido.
ACTUALIZACIÓN: esto se solucionará en Entity Framework versión 6.1.0, que actualmente está disponible en versión beta.