J'ai une table dans ma base de données appelée SEntries (voir ci-dessous l'instruction CREATE TABLE). Il a une clé primaire, quelques clés étrangères et rien de spécial à ce sujet. Ma base de données contient de nombreuses tables similaires à celle-ci, mais pour une raison quelconque, cette table s'est terminée par une colonne "Discriminator" sur la classe de proxy EF.
Voici comment la classe est déclarée 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; }
...
}
Lorsque j'essaie d'ajouter une nouvelle ligne à cette table, j'obtiens le message d'erreur suivant:
System.Data.SqlClient.SqlException: Invalid column name 'Discriminator'.
Ce problème ne se produit que si vous héritez de votre classe C # d'une autre classe, mais que SEntry n'hérite de rien (comme vous pouvez le voir ci-dessus).
En plus de cela, une fois que je reçois l'info-bulle sur le débogueur lorsque je passe la souris sur l'instance EMData pour la propriété SEntries, il affiche:
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...
Avez-vous des suggestions ou des idées pour aller au fond des choses? J'ai essayé de renommer la table, la clé primaire et quelques autres choses, mais rien ne fonctionne.
Table 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
Il s'avère que Entity Framework supposera que toute classe héritant d'une classe POCO mappée à une table de la base de données nécessite une colonne Discriminator, même si la classe dérivée ne sera pas enregistrée dans la base de données.
La solution est assez simple et il vous suffit d'ajouter [NotMapped]
comme attribut de la classe dérivée.
Exemple:
class Person
{
public string Name { get; set; }
}
[NotMapped]
class PersonViewModel : Person
{
public bool UpdateProfile { get; set; }
}
À présent, même si vous mappez la classe Person à la table Person de la base de données, aucune colonne "Discriminator" ne sera créée car la classe dérivée a [NotMapped]
.
Comme astuce supplémentaire, vous pouvez utiliser [NotMapped]
vers les propriétés que vous ne souhaitez pas associer à un champ de la base de données.
Voici la syntaxe de l'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);
}
Je viens de rencontrer cela et mon problème était dû au fait que deux entités avec le System.ComponentModel.DataAnnotations.Schema.TableAttribute
faisant référence à la même table.
par exemple:
[Table("foo")]
public class foo
{
// some stuff here
}
[Table("foo")]
public class fooExtended
{
// more stuff here
}
changer le second de foo
en foo_extended
a corrigé cela pour moi et j'utilise désormais Table par type (TPT)
Cela se produit également si vous avez une classe de base et une ou plusieurs sous-classes, au moins une des sous-classes introduisant des propriétés supplémentaires:
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 ceux-ci sont mappés dans le DbContext
comme ci-dessous, l'erreur "'Nom de colonne non valide' Discriminator '" se produit lorsqu'un type quelconque basé sur le type Folder
de base est utilisé:
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");
}
J'ai trouvé que pour résoudre le problème, nous extrayions les accessoires de Folder
dans une classe de base (qui n'est pas mappée dans OnModelCreating()
) comme si - OnModelCreating
ne devait pas être modifié:
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; }
}
Cela élimine le problème, mais je ne sais pas pourquoi!
Je reçois l'erreur dans une autre situation, et voici le problème et la solution:
J'ai 2 classes dérivées d'une même classe de base nommée LevledItem:
public partial class Team : LeveledItem
{
//Everything is ok here!
}
public partial class Story : LeveledItem
{
//Everything is ok here!
}
Mais dans leur DbContext, j'ai copié du code mais j'ai oublié de changer l'un des noms de classe:
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));
}
Oui, la deuxième carte <Équipe> devrait être Carte <Histoire>. Et cela m'a coûté une demi-journée pour le comprendre!
cette erreur arrive avec moi parce que j'ai fait ce qui suit
Update Model from database
_ dans Edmx) I renommé manuellement Nom de la propriété pour correspondre au changement de schéma de base de donnéesBien que tout cela, j'ai eu cette erreur
alors what to do
Update Model from database
cela régénérera le modèle et le cadre d'entité will
notgive you this error
espérons que cela vous aide
J'ai eu un problème similaire, pas exactement les mêmes conditions et puis j'ai vu ce post . J'espère que ça aide quelqu'un. Apparemment, j'utilisais l'un de mes modèles d'entité EF, une classe de base pour un type qui n'était pas spécifié en tant que base de données définie dans mon contexte de base de données. Pour résoudre ce problème, j'ai dû créer une classe de base possédant toutes les propriétés communes aux deux types et hériter de la nouvelle classe de base parmi les deux types.
Exemple:
//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;}
}
Ancien Q, mais pour la postérité ... cela se produit également (.NET Core 2.1) si vous avez une propriété de navigation à auto-référencement ("Parent" ou "Enfants" du même type) mais que le nom de la propriété Id n'est pas ce qu'il est EF attend. C'est-à-dire que j'avais une propriété "Id" sur ma classe appelée WorkflowBase
et qu'elle contenait un tableau d'étapes enfants associées, qui étaient également de type WorkflowBase
, et il essayait sans cesse de les associer. avec un "WorkflowBaseId" non existant (le nom que je suppose qu'il préfère comme défaut naturel/conventionnel). Je devais le configurer explicitement en utilisant HasMany()
, WithOne()
et HasConstraintName()
pour lui indiquer comment parcourir. Mais j'ai passé quelques heures à penser que le problème résidait dans la cartographie "locale" de la clé primaire de l'objet, que j'ai essayé de corriger, mais qui fonctionnait probablement toujours.