Код EF сначала "недопустимое имя столбца "дискриминатор"", но без наследования

у меня есть таблица в моей базе данных под названием SEntries (см. ниже инструкцию CREATE TABLE). У него есть первичный ключ, пара внешних ключей и ничего особенного. У меня есть много таблиц в моей базе данных, подобных этой, но по какой-то причине эта таблица закончилась столбцом "дискриминатора" в прокси-классе EF.

вот как класс объявляется в 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; }
            ...
    }

когда я пытаюсь добавить новую строку в эту таблицу, я получаю ошибка:

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

эта проблема возникает, только если вы наследуете свой класс C# от другого класса, но SEntry не наследует ничего (как вы можете видеть выше).

в дополнение к этому, как только я получу подсказку инструмента на отладчике, когда я наведу указатель мыши на экземпляр EMData для свойства SEntries, он отобразит:

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

любые предложения или идеи, где добраться до сути этой проблемы? Я попытался переименовать таблицу, первичный ключ и несколько других вещи, но ничего не работает.

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

7 ответов


оказывается, что Entity Framework будет предполагать, что любой класс, наследующий от класса POCO, который сопоставлен с таблицей в базе данных, требует столбца дискриминатора, даже если производный класс не будет сохранен в БД.

решение довольно простое, и вам просто нужно добавить [NotMapped] как атрибут производного класса.

пример:

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

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

теперь, даже если вы сопоставляете класс Person с таблицей Person в базе данных, " дискриминатор" столбец не будет создан, поскольку производный класс имеет [NotMapped].

в качестве дополнительного наконечника вы можете использовать [NotMapped] к свойствам, которые вы не хотите сопоставлять с полем в БД.


вот синтаксис Fluent API.

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

}

Я только что столкнулся с этим, и моя проблема была вызвана наличием двух сущностей с System.ComponentModel.DataAnnotations.Schema.TableAttribute ссылка на ту же таблицу.

например:

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

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

изменение второго из foo to foo_extended исправлено это для меня, и теперь я использую таблицу для каждого типа (TPT)


другой сценарий, где это происходит, когда у вас есть базовый класс и один или несколько подклассов, где по крайней мере один из подклассов вводит дополнительные свойства:

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

если они отображаются в DbContext как показано ниже, ошибка "недопустимое имя столбца "дискриминатор "" возникает, когда любой тип на основе 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");
}

я обнаружил, что для исправления проблемы мы извлекаем реквизит Folder на базовый класс (который не отображается в OnModelCreating()) вот так - OnModelCreating должно быть без изменений:

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

это устраняет проблему, но я не знаю, почему!


Я получаю ошибку в другой ситуации, и вот проблема и решение:

у меня есть 2 класса, производные от того же базового класса с именем LevledItem:

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

но в их DbContext я скопировал некоторый код, но забыл изменить одно из имен класса:

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

да, вторая карта должна быть Map. И мне потребовалось полдня, чтобы понять это!


эта ошибка происходит со мной, потому что я сделал следующее

  1. Я изменил имя столбца таблицы в базе данных
  2. (Я не использовал Update Model from database в Edmx) я переименовал вручную имя свойства, чтобы соответствовать изменению схемы базы данных
  3. Я сделал рефакторинг, чтобы изменить имя свойства в классе, чтобы быть таким же, как схема базы данных и модели в Edmx

несмотря на все это, я получил эту ошибку

так what to do

  1. Я удалил модель из Edmx
  2. щелкните правой кнопкой мыши и Update Model from database

это восстановит модель и entity framework will не give you this error

надеюсь, что это поможет вам


У меня была аналогичная проблема, не совсем те же условия, а затем я увидел этот пост. Надеюсь, это кому-то поможет. По-видимому, я использовал одну из моих моделей сущностей EF базовый класс для типа, который не был указан как набор БД в моем dbcontext. Чтобы устранить эту проблему, мне пришлось создать базовый класс, который имел все свойства, общие для двух типов и наследовал от нового базового класса среди двух типов.

пример:

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

    }