entity framework - mvc - Código EF Primero "Nombre de columna inválido ''Discriminador''" pero no herencia
entity framework database first (6)
Acabo de encontrar esto y mi problema fue causado por tener dos entidades con System.ComponentModel.DataAnnotations.Schema.TableAttribute
referencia a la misma tabla.
por ejemplo:
[Table("foo")]
public class foo
{
// some stuff here
}
[Table("foo")]
public class fooExtended
{
// more stuff here
}
cambiar el segundo de foo
a foo_extended
arregló esto y ahora estoy usando Table Per Type (TPT)
Tengo una tabla en mi base de datos llamada SEntries (ver abajo la declaración CREATE TABLE). Tiene una clave principal, un par de claves externas y nada especial al respecto. Tengo muchas tablas en mi base de datos similares a esa, pero por alguna razón, esta tabla terminó con una columna "Discriminador" en la clase EF Proxy.
Así es como se declara la clase en C #:
public class SEntry
{
public long SEntryId { get; set; }
public long OriginatorId { get; set; }
public DateTime DatePosted { get; set; }
public string Message { get; set; }
public byte DataEntrySource { get; set; }
public string SourceLink { get; set; }
public int SourceAppId { get; set; }
public int? LocationId { get; set; }
public long? ActivityId { get; set; }
public short OriginatorObjectTypeId { get; set; }
}
public class EMData : DbContext
{
public DbSet<SEntry> SEntries { get; set; }
...
}
Cuando trato de agregar una nueva fila a esa tabla, obtengo el error:
System.Data.SqlClient.SqlException: Invalid column name ''Discriminator''.
Este problema solo ocurre si estás heredando tu clase C # de otra clase, pero SEntry no está heredando nada (como puedes ver más arriba).
Además de eso, una vez que obtengo la información sobre herramientas en el depurador cuando paso el ratón sobre la instancia EMData para la propiedad SEntries, aparece:
base {System.Data.Entity.Infrastructure.DbQuery<EM.SEntry>} = {SELECT
[Extent1].[Discriminator] AS [Discriminator],
[Extent1].[SEntryId] AS [SEntryId],
[Extent1].[OriginatorId] AS [OriginatorId],
[Extent1].[DatePosted] AS [DatePosted],
[Extent1].[Message] AS [Message],
[Extent1].[DataEntrySource] AS [DataE...
¿Alguna sugerencia o idea para llegar al fondo de este problema? Traté de cambiar el nombre de la tabla, la clave principal y algunas otras cosas, pero nada funciona.
Tabla de SQL:
CREATE TABLE [dbo].[SEntries](
[SEntryId] [bigint] IDENTITY(1125899906842624,1) NOT NULL,
[OriginatorId] [bigint] NOT NULL,
[DatePosted] [datetime] NOT NULL,
[Message] [nvarchar](500) NOT NULL,
[DataEntrySource] [tinyint] NOT NULL,
[SourceLink] [nvarchar](100) NULL,
[SourceAppId] [int] NOT NULL,
[LocationId] [int] NULL,
[ActivityId] [bigint] NULL,
[OriginatorObjectTypeId] [smallint] NOT NULL,
CONSTRAINT [PK_SEntries] PRIMARY KEY CLUSTERED
(
[SEntryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[SEntries] WITH CHECK ADD CONSTRAINT [FK_SEntries_ObjectTypes] FOREIGN KEY([OriginatorObjectTypeId])
REFERENCES [dbo].[ObjectTypes] ([ObjectTypeId])
GO
ALTER TABLE [dbo].[SEntries] CHECK CONSTRAINT [FK_SEntries_ObjectTypes]
GO
ALTER TABLE [dbo].[SEntries] WITH CHECK ADD CONSTRAINT [FK_SEntries_SourceApps] FOREIGN KEY([SourceAppId])
REFERENCES [dbo].[SourceApps] ([SourceAppId])
GO
ALTER TABLE [dbo].[SEntries] CHECK CONSTRAINT [FK_SEntries_SourceApps]
GO
Aquí está la sintaxis de la API Fluent.
http://blogs.msdn.com/b/adonet/archive/2010/12/06/ef-feature-ctp5-fluent-api-samples.aspx
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName {
get {
return this.FirstName + " " + this.LastName;
}
}
}
class PersonViewModel : Person
{
public bool UpdateProfile { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ignore a type that is not mapped to a database table
modelBuilder.Ignore<PersonViewModel>();
// ignore a property that is not mapped to a database column
modelBuilder.Entity<Person>()
.Ignore(p => p.FullName);
}
Me sale el error en otra situación, y aquí están el problema y la solución:
Tengo 2 clases derivadas de una misma clase base llamada LevledItem:
public partial class Team : LeveledItem
{
//Everything is ok here!
}
public partial class Story : LeveledItem
{
//Everything is ok here!
}
Pero en su DbContext, copié un código pero me olvidé de cambiar uno de los nombres de clase:
public class MFCTeamDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Other codes here
modelBuilder.Entity<LeveledItem>()
.Map<Team>(m => m.Requires("Type").HasValue(ItemType.Team));
}
public class ProductBacklogDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Other codes here
modelBuilder.Entity<LeveledItem>()
.Map<Team>(m => m.Requires("Type").HasValue(ItemType.Story));
}
Sí, el segundo Mapa <Equipo> debería ser Mapa <Historia>. ¡Y me costó medio día descubrirlo!
Otro escenario donde esto ocurre es cuando tienes una clase base y una o más subclases, donde al menos una de las subclases introduce propiedades adicionales:
class Folder {
[key]
public string Id { get; set; }
public string Name { get; set; }
}
// Adds no props, but comes from a different view in the db to Folder:
class SomeKindOfFolder: Folder {
}
// Adds some props, but comes from a different view in the db to Folder:
class AnotherKindOfFolder: Folder {
public string FolderAttributes { get; set; }
}
Si se asignan en el DbContext
como se DbContext
a continuación, se produce el error "''Invalid column name'' Discriminator ''" cuando se accede a cualquier tipo basado en el tipo de base de la Folder
:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Folder>().ToTable("All_Folders");
modelBuilder.Entity<SomeKindOfFolder>().ToTable("Some_Kind_Of_Folders");
modelBuilder.Entity<AnotherKindOfFolder>().ToTable("Another_Kind_Of_Folders");
}
Descubrí que, para solucionar el problema, extrajimos los puntales de Folder
a una clase base (que no está mapeada en OnModelCreating()
) así que - OnModelCreating
debería haber cambiado:
class FolderBase {
[key]
public string Id { get; set; }
public string Name { get; set; }
}
class Folder: FolderBase {
}
class SomeKindOfFolder: FolderBase {
}
class AnotherKindOfFolder: FolderBase {
public string FolderAttributes { get; set; }
}
Esto elimina el problema, ¡pero no sé por qué!
Resulta que Entity Framework supondrá que cualquier clase que herede de una clase POCO que está mapeada en una tabla en la base de datos requiere una columna Discriminador, incluso si la clase derivada no se guardará en la base de datos.
La solución es bastante simple y solo necesita agregar [NotMapped]
como un atributo de la clase derivada.
Ejemplo:
class Person
{
public string Name { get; set; }
}
[NotMapped]
class PersonViewModel : Person
{
public bool UpdateProfile { get; set; }
}
Ahora, incluso si asigna la clase Person a la tabla Person en la base de datos, no se creará una columna "Discriminator" porque la clase derivada tiene [NotMapped]
.
Como sugerencia adicional, puede usar [NotMapped]
en las propiedades que no desea asignar a un campo en el DB.
este error pasó conmigo porque hice lo siguiente
- Cambié el nombre de columna de la tabla en la base de datos
- (No usé
Update Model from database
en Edmx) Renueve manualmente el nombre de la propiedad para que coincida con el cambio en el esquema de la base de datos - Hice algunas refactorizaciones para cambiar el nombre de la propiedad en la clase para que sea el mismo que el esquema de la base de datos y los modelos en Edmx
Aunque todo esto, obtuve este error
entonces what to do
- Eliminé el modelo de Edmx
- Haga clic derecho y
Update Model from database
esto regenerará el modelo, y el marco de la entidad no le give you this error
espero que esto te ayude