172

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
Ingako
  • 393
  • 4
  • 14
Marcelo Calbucci
  • 5,845
  • 3
  • 18
  • 22
  • 18
    For the next person who'll spend some time trying to figure this out, what happened is that in another place on the code, I had a class that inherited from SEntry, even though it's not a class that would ever be stored on the DB. So all that I needed to do was to add [NotMapped] as an attribute of that class! – Marcelo Calbucci Jul 02 '11 at 00:29
  • 1
    I am getting this error if i don't put [NotMapped] on ApplicationUser class in Identitymodel.cs – Heemanshu Bhalla Nov 21 '18 at 18:56
  • I have a similar issue, posted in detail at https://stackoverflow.com/questions/75333465/using-inherited-entity-class-in-asp-net-ef-core – Vimal Upadhyay Feb 03 '23 at 09:03

8 Answers8

356

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.

Amirhossein Mehrvarzi
  • 18,024
  • 7
  • 45
  • 70
Marcelo Calbucci
  • 5,845
  • 3
  • 18
  • 22
  • 7
    ok so there goes 3 hours of my life ;( but tyvm all the same. I should also add just to be clear... the derived classes can be all the way over in the corner not in any way used re: persistence and EF will still try and draw them in...very confusing. – rism May 04 '13 at 12:38
  • 13
    If you don't find [NotMapped] please add a reference to: "System.ComponentModel.DataAnnotations" to the project from "Assembly Framework". – XandrUu Jan 23 '14 at 16:32
  • 10
    using System.ComponentModel.DataAnnotations.Schema; – ygaradon Feb 13 '14 at 18:30
  • 1
    How to fix the error "Mapping and metadata information could not be found for EntityType", when trying to add the viewmodel to the db collection? – Xavier John Apr 18 '14 at 21:25
  • 1
    OMG! I deliberately created a DTO class that inherits the Entity to avoid using NotMapped.... but NOooooooo... :( For some reason getting the Base Entity wants to upcast to my DTO.. I don't get it.. absurd. – Piotr Kula Feb 23 '17 at 15:15
  • 10
    but in my case I have inherited a class to add column in db table using child class. So I cant use this notmapped attribute to get it working. What should be my solution in this case? – sohaib javed Apr 04 '17 at 20:41
  • 4
    in my case adding not mapped didn't helped. i have notmapped in all viewmodels – Heemanshu Bhalla Nov 21 '18 at 10:01
  • I am getting this error. So I added the field (ContactNumberTypeId) with a [NotMapped] and now it's says it can't find field ContactNumberTypeId1. And if I add that field it can't find ContactNumberTypeId2. – Nigel Ellis Aug 01 '19 at 14:01
  • 1
    9 years later and I am also getting this error. I do have a classed inheriting from the POCO and like Heemanshu I added [NotMapped] and it did not work. – Clarence Jul 31 '20 at 04:54
  • Until I realized that I had multiple classes inheriting from my POCO class. Once I [NotMapped] them all, it worked. I tried to add this to my previous comment, but was stopped due to some time error – Clarence Jul 31 '20 at 05:09
  • What if it is mapped though? – CarComp Oct 14 '22 at 12:41
47

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

}
Walter Stabosz
  • 7,447
  • 5
  • 43
  • 75
  • Wouldn't it be better just to add the `[NotMapped]` attribute? – Keith Jan 15 '16 at 20:14
  • 2
    @Keith my answer is how to ignore a column using the Fluent API, which does not use attributes such as [NotMapped] – Walter Stabosz Jan 17 '16 at 02:23
  • 1
    Keith this is the preferred answer I think because are now moving towards a code-first standard and Walter's answer is better suited for this scenario especially if you end up using db migrations. – Trevor Jul 24 '16 at 05:11
  • Where you have the opposite problem (i.e. and EF bound class that inherits from a POCO class) this was the only way I could get that to work without polluting the data model with EF. – Paul Michaels Jul 09 '18 at 14:17
9

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)

Seph
  • 8,472
  • 10
  • 63
  • 94
  • This did not work for me:`The entity types 'AtencionMedica' and 'AtencionMedicaAP' cannot share table 'AtencionMedicas' because they are not in the same type hierarchy` – James Reategui Sep 08 '15 at 18:51
  • Thanks, helped me, had the same issue using the fluent API: `var entity = modelBuilder.Entity().ToTable("ENTITY_TABLE")`, and then another line using either the same `EntityObject` or the same `ENTITY_TABLE`. – Mathijs Flietstra Nov 06 '17 at 13:23
8

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

    }
KwakuCsc
  • 169
  • 2
  • 4
7

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!

meataxe
  • 969
  • 13
  • 33
  • thanks, meataxe -- that cost me an hour or two, but the worst part was, I must have had this problem before, because I had the base classes all set up. Dumber me a year later says, "Hey, looks like this base class isn't doing anything. I think I'll just remove it..." And there went an hour of my life that I'll never get back. WHY IS THIS REQUIRED? I wish I understood EF better. – Wellspring Feb 12 '20 at 22:26
2

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!

cheny
  • 2,545
  • 1
  • 24
  • 30
2

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.

tntwyckoff
  • 539
  • 5
  • 17
1

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

Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92