データベースにSEntriesというテーブルがあります(以下のCREATE TABLEステートメントを参照)。主キー、いくつかの外部キーがあり、特別なものはありません。データベースには多くのテーブルがありますが、何らかの理由で、このテーブルにはEFプロキシクラスの「Discriminator」列があります。
これは、クラスが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が何からも継承していない場合にのみ発生します(上記を参照)。
それに加えて、SEntriesプロパティのEMDataインスタンスの上にマウスを置いたときにデバッガのツールチップを取得すると、次のように表示されます。
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
Entity Frameworkは、派生クラスがDBに保存されない場合でも、データベースのテーブルにマップされるPOCOクラスから継承するクラスにはDiscriminator列が必要であると想定していることがわかります。
解決策は非常に簡単で、派生クラスの属性として[NotMapped]
を追加するだけです。
例:
class Person
{
public string Name { get; set; }
}
[NotMapped]
class PersonViewModel : Person
{
public bool UpdateProfile { get; set; }
}
これで、PersonクラスをデータベースのPersonテーブルにマップしても、派生クラスには[NotMapped]
があるため、「Discriminator」列は作成されません。
追加のヒントとして、[NotMapped]
を使用して、DBのフィールドにマップしたくないプロパティに使用できます。
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
を持つ2つのエンティティが原因で問題が発生しました。
例えば:
[Table("foo")]
public class foo
{
// some stuff here
}
[Table("foo")]
public class fooExtended
{
// more stuff here
}
2番目のものをfoo
からfoo_extended
に変更すると、これが修正され、Table Per Type(TPT)を使用するようになりました
これが発生する別のシナリオは、基本クラスと1つ以上のサブクラスがあり、少なくとも1つのサブクラスが追加のプロパティを導入する場合です。
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
ベースタイプに基づくタイプにアクセスすると、「 'Invalid column name' Discriminator '」エラーが発生します。
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; }
}
これにより問題は解消されますが、理由はわかりません!
別の状況でエラーが発生しましたが、ここに問題と解決策があります:
LevledItemという名前の同じ基本クラスから派生した2つのクラスがあります。
public partial class Team : LeveledItem
{
//Everything is ok here!
}
public partial class Story : LeveledItem
{
//Everything is ok here!
}
しかし、DbContextでは、いくつかのコードをコピーしましたが、クラス名の1つを変更することを忘れました。
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));
}
はい、2番目のMap <Team>はMap <Story>である必要があります。そして、それを理解するのに半日かかりました!
私は次のことをしたので、このエラーは私で起こります
Update Model from database
を使用しませんでした)データベーススキーマの変更に合わせてプロパティ名を手動で変更しましたこのすべてですが、このエラーが発生しました
what to do
Update Model from database
これにより、モデルとエンティティフレームワークが再生成されますwill
notgive you this error
これがお役に立てば幸いです
まったく同じ条件ではなく、同様の問題が発生したので、 この投稿 を見ました。それが誰かを助けることを願っています。どうやら、EFエンティティモデルの1つを使用して、dbcontextでdbセットとして指定されていないタイプの基本クラスをモデル化していたようです。この問題を解決するには、2つのタイプに共通するすべてのプロパティを持つ基本クラスを作成し、2つのタイプ間で新しい基本クラスから継承する必要がありました。
例:
//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;}
}
古いQですが、後世のために...自己参照ナビゲーションプロパティ(同じタイプの「親」または「子供」)があり、Idプロパティ名がそうではない場合にも発生します(.NET Core 2.1) EFは期待しています。つまり、クラスにはWorkflowBase
という名前の「Id」プロパティがあり、関連する子ステップの配列もありました。これらのステップもWorkflowBase
型であり、存在しない「WorkflowBaseId」(名前は自然/従来のデフォルトとして好むと思います)。 HasMany()
、WithOne()
、およびHasConstraintName()
を使用して明示的に設定し、トラバース方法を指示する必要がありました。しかし、私は問題がオブジェクトの主キーの「ローカル」マッピングにあると考えて数時間を費やしました。これはさまざまな方法を修正しようとしましたが、おそらく常に機能していました。