Код EF сначала «Неверное имя столбца« Дискриминатор »», но нет наследования - PullRequest
141 голосов
/ 02 июля 2011

В моей базе данных есть таблица 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 ]

299 голосов
/ 05 июля 2011

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

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

Пример:

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

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

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

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

42 голосов
/ 21 февраля 2013

Вот синтаксис 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);

}
7 голосов
/ 17 октября 2014

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

например:

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

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

изменение второго значения с foo на foo_extended исправило это для меня, и теперь я использую Table Per Type (TPT)

3 голосов
/ 19 февраля 2015

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

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 голосов
/ 07 декабря 2014

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

У меня есть 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));
    }

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

1 голос
/ 03 октября 2018

У меня была похожая проблема, не совсем те же условия, и тогда я увидел этот пост .Надеюсь, это кому-нибудь поможет.Очевидно, я использовал одну из моих моделей сущностей 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;}

    }
1 голос
/ 22 августа 2016

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

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

Хотя всеиз этого я получил эту ошибку

так what to do

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

это восстановит модель, а структура сущностей will не give you this error

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...