2011-07-01 11 views
120

Tengo una tabla en mi base de datos llamada SEntries (ver abajo la instrucció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.Código EF Primero "Nombre de columna inválido 'Discriminador'" pero no herencia

Esto es cómo 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 intento agregar una nueva fila a la tabla, me sale el error:

System.Data.SqlClient.SqlException: Invalid column name 'Discriminator'. 

Este problema sólo se produce 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 consiga la herramienta de punta en el depurador cuando puntero del ratón sobre la instancia EMData para la propiedad centinelas, se muestra:

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... 

Cualquier sugerencia o ideas donde para llegar a la fondo de este problema? Traté de cambiar el nombre de la tabla, la clave principal y algunas otras cosas, pero nada funciona.

SQL-Tabla:

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 
+11

Para la próxima persona que pasará algún tiempo tratando de resolver esto, lo que sucedió es que en otro lugar en el código, tuve una clase que heredó de SEntry, a pesar de que no es una clase que alguna vez sería almacenado en la base de datos. ¡Entonces todo lo que tenía que hacer era agregar [NotMapped] como un atributo de esa clase! –

Respuesta

256

Resulta que Entity Framework asumirá que cualquier clase que hereda de una clase POCO que está asignado a una tabla en la base de datos requiere una columna de 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 de persona a persona en la mesa de la base de datos, una columna "discriminador" no se creará porque la clase derivada tiene [NotMapped].

Como consejo adicional, puede usar [NotMapped] en propiedades que no desea asignar a un campo en la base de datos.

+5

ok, así que van 3 horas de mi vida; (pero de todos modos, también debería agregar solo para ser claro ... las clases derivadas pueden estar completas en la esquina, no de ninguna manera usada re: persistencia y EF aún intentará dibujarlos ... muy confuso. – rism

+11

Si no encuentra [NotMapped], agregue una referencia a: "System.ComponentModel.DataAnnotations" al proyecto desde "Assembly Framework". – XandrUu

+8

using System. ComponentModel.DataAnnotations.Schema; – ygaradon

40

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); 

} 
+1

gracias por señalar cómo ignorar una propiedad – Adi

+0

¿No sería mejor agregar el atributo '[NotMapped]'? – Keith

+1

@Keith mi respuesta es cómo ignorar una columna usando la API de Fluent, que no usa atributos como [NoModificado] –

6

yo sólo encontré con esto y mi problema fue causado por tener dos entidades, tanto con el System.ComponentModel.DataAnnotations.Schema.TableAttribute refiriéndose a la misma mesa.

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 fijo esto para mí y ahora estoy usando la tabla según el tipo (TPT)

+0

Esto no funcionó para mí: 'Los tipos de entidad 'AtencionMedica' y 'AtencionMedicaAP' no pueden compartir la tabla 'AtencionMedicas' porque no están en la misma jerarquía de tipos' –

+0

Gracias, me ayudó, tuve el mismo problema al usar la API con fluidez: 'var entity = modelBuilder.Entity (). ToTable (" ENTITY_TABLE ")', y luego otra línea usando el mismo 'EntityObject' o el mismo' ENTITY_TABLE'. –

1

me sale el error en otra situación, y aquí están el problema y la solución:

tengo 2 clases derivadas de una llamada LevledItem misma clase base:

public partial class Team : LeveledItem 
{ 
    //Everything is ok here! 
} 
public partial class Story : LeveledItem 
{ 
    //Everything is ok here! 
} 

Pero en su DbContext, he copiado algo de código, pero se olvide de cambiar uno del nombre 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> debe haber Mapa < historia>. ¡Y me costó medio día descubrirlo!

2

Otro escenario en el que esto ocurre es cuando se tiene una clase base y una o más subclases, donde al menos una de las subclases introducir 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 éstos se asignan en el DbContext como el de abajo, el "'nombre de columna no válido 'Discriminador'" error se produce cuando se accede a cualquier tipo basado en Folder tipo base:

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"); 
} 

he encontrado que para solucionar el problema, extraemos los puntales de Folder a una clase base (que no está mapeado en OnModelCreating()) de esta manera - 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 yo no sé por qué!

+0

Esto prácticamente hace que las clases derivadas sean inútiles ... – Jerther

1

este error ocurra conmigo porque hice la siguiente

  1. Me cambió el nombre de columna de la tabla de la base de datos
  2. (No solía Update Model from database en EDMX) Me cambió el nombre manualmente el nombre de la propiedad para que coincida con el cambio de esquema de base de
  3. hice un poco de refactorización para cambiar el nombre de la propiedad de la clase a ser el mismo que el esquema de base de datos y modelos en EDMX

Aunque al l de esto, me dio este mensaje

por lo what to do

  1. He eliminado el modelo de EDMX
  2. Haga clic derecho y Update Model from database

esto va a regenerar el modelo y el marco de la entidad willnogive you this error

h Oye esto ayuda

Cuestiones relacionadas