EF Code First "Invalid column name 'Discriminator'" but no inheritance

Entity FrameworkEf Code-First

Entity Framework Problem Overview


I have a table in my database called SEntries (see below the CREATE TABLE statement). It has a primary key, a couple of foreign keys and nothing special about it. I have many tables in my database similar to that one, but for some reason, this table ended up with a "Discriminator" column on the EF Proxy Class.

This is how the class is declared in 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; }
            ...
    }

When I try to add a new row to that table, I get the error:

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

This problem only occurs if you are inheriting your C# class from another class, but SEntry is not inheriting from anything (as you can see above).

In addition to that, once I get the tool-tip on the debugger when I mouse over the EMData instance for the SEntries property, it displays:

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

Any suggestions or ideas where to get to the bottom of this issue? I tried renaming the table, the primary key and a few other things, but nothing works.

SQL-Table:

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

Entity Framework Solutions


Solution 1 - Entity Framework

Turns out that Entity Framework will assume that any class that inherits from a POCO class that is mapped to a table on the database requires a Discriminator column, even if the derived class will not be saved to the DB.

The solution is quite simple and you just need to add [NotMapped] as an attribute of the derived class.

Example:

class Person
{
    public string Name { get; set; }
}

[NotMapped]
class PersonViewModel : Person
{
    public bool UpdateProfile { get; set; }
}

Now, even if you map the Person class to the Person table on the database, a "Discriminator" column will not be created because the derived class has [NotMapped].

As an additional tip, you can use [NotMapped] to properties you don't want to map to a field on the DB.

Solution 2 - Entity Framework

Here is the Fluent API syntax.

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

Solution 3 - Entity Framework

I just encountered this and my problem was caused by having two entities both with the System.ComponentModel.DataAnnotations.Schema.TableAttribute referring to the same table.

for example:

[Table("foo")]
public class foo
{
    // some stuff here
}

[Table("foo")]
public class fooExtended
{
    // more stuff here
}

changing the second one from foo to foo_extended fixed this for me and I'm now using Table Per Type (TPT)

Solution 4 - Entity Framework

I had a similar problem, not exactly the same conditions and then i saw this post. Hope it helps someone. Apparently i was using one of my EF entity models a base class for a type that was not specified as a db set in my dbcontext. To fix this issue i had to create a base class that had all the properties common to the two types and inherit from the new base class among the two types.

Example:

//Bad Flow
    //class defined in dbcontext as a dbset
    public class Customer{ 
       public int Id {get; set;}
       public string Name {get; set;}
    }

    //class not defined in dbcontext as a dbset
    public class DuplicateCustomer:Customer{ 
       public object DuplicateId {get; set;}
    }


    //Good/Correct flow*
    //Common base class
    public class CustomerBase{ 
       public int Id {get; set;}
       public string Name {get; set;}
    }
    
    //entity model referenced in dbcontext as a dbset
    public class Customer: CustomerBase{
      
    }
    
    //entity model not referenced in dbcontext as a dbset
    public class DuplicateCustomer:CustomerBase{
    
       public object DuplicateId {get; set;}
    
    }

Solution 5 - Entity Framework

Another scenario where this occurs is when you have a base class and one or more subclasses, where at least one of the subclasses introduce extra properties:

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

If these are mapped in the DbContext like below, the "'Invalid column name 'Discriminator'" error occurs when any type based on Folder base type is accessed:

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

I found that to fix the issue, we extract the props of Folder to a base class (which is not mapped in OnModelCreating()) like so - OnModelCreating should be unchanged:

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

This eliminates the issue, but I don't know why!

Solution 6 - Entity Framework

I get the error in another situation, and here are the problem and the solution:

I have 2 classes derived from a same base class named LevledItem:

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

But in their DbContext, I copied some code but forget to change one of the class name:

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

Yes, the second Map< Team> should be Map< Story>. And it cost me half a day to figure it out!

Solution 7 - Entity Framework

Old Q, but for posterity...it also also happens (.NET Core 2.1) if you have a self-referencing navigation property ("Parent" or "Children" of the same type) but the Id property name isn't what EF expects. That is, I had an "Id" property on my class called WorkflowBase, and it had an array of related child steps, which were also of type WorkflowBase, and it kept trying to associate them with a non-existent "WorkflowBaseId" (the name i suppose it prefers as a natural/conventional default). I had to explicitly configure it using HasMany(), WithOne(), and HasConstraintName() to tell it how to traverse. But I spent a few hours thinking the problem was in 'locally' mapping the object's primary key, which i attempted to fix a bunch of different ways but which was probably always working.

Solution 8 - Entity Framework

this error happen with me because I did the following

  1. I changed Column name of table in database
  2. (I did not used Update Model from database in Edmx) I Renamed manually Property name to match the change in database schema
  3. I did some refactoring to change name of the property in the class to be the same as database schema and models in Edmx

Although all of this, I got this error

so what to do

  1. I Deleted the model from Edmx
  2. Right Click and Update Model from database

this will regenerate the model, and entity framework will not give you this error

hope this help you

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMarcelo CalbucciView Question on Stackoverflow
Solution 1 - Entity FrameworkMarcelo CalbucciView Answer on Stackoverflow
Solution 2 - Entity FrameworkWalter StaboszView Answer on Stackoverflow
Solution 3 - Entity FrameworkSephView Answer on Stackoverflow
Solution 4 - Entity FrameworkKwakuCscView Answer on Stackoverflow
Solution 5 - Entity FrameworkmeataxeView Answer on Stackoverflow
Solution 6 - Entity FrameworkchenyView Answer on Stackoverflow
Solution 7 - Entity FrameworktntwyckoffView Answer on Stackoverflow
Solution 8 - Entity FrameworkBasheer AL-MOMANIView Answer on Stackoverflow