2016-07-07 4 views
2

データベースの一部のテーブルを表すEntityFramework 6データコンテキストを作成しました。以下に引用する再プロコードの場合、(Items)何らかの辞書の項目、もう一つの項目(Notes)には項目に付けることができるいくつかの音符が含まれています。項目には0以上の音符を含めることができます。ここでは難しいことはありません。各テーブルには1つのPOCOオブジェクトしかありません。これが私がやっていることです。 EF6:テーブル分割を行わずに「エンティティタイプがテーブルを共有できません」エラー

"The entity types 'EfItem' and 'Item' cannot share table 'Item' because they are not in the same type hierarchy or do not have a valid one to one foreign key relationship with matching primary keys between them." 

は今、このエラーは、いくつかのオブジェクトが同じSQLテーブルにマッピングされている場合のために有意義であると思われるが、これはここにそうではありません。私の DbContextからデータベースを初期化するとき、まだ、私はエラーを取得します。私はそれぞれのテーブルに1つの具体的なオブジェクトしか持っていません。では、このエラーの原因は何でしょうか?

私はレプロソリューションを作成しました。詳細はこちらのhttps://1drv.ms/u/s!AMHCfliT740PkK9Hからダウンロードできます。

このソリューションの主なポイントは、クライアントコードを、RDBMS、NoSql DBなどの選択したストレージテクノロジに完全に無関係に保つ必要があることです。この目的のために、私のソリューションでは、 "コア"プロジェクトは、PCLで、インターフェイスのみを扱う高レベルリポジトリ用のインターフェイスを含んでいます。たとえば、具体的な型を直接使用するのではなく、AddItem(IItem item)のようなメソッドがあります。

これにより、選択した技術の必要に応じて具体的なオブジェクトをカスタマイズすることができます。例えば、EFオブジェクトには「親」ナビゲーションプロパティが必要ですが、MongoDBでは意味がありません。もちろん、このアプローチの欠点は、ほとんどの具体的な型を再定義して、インタフェース実装の対応に変換することです。たとえば、EFではEfItemオブジェクトがあり、IItemに変換できます。このオブジェクトはこのインタフェースを実装していませんが、単純にそのインタフェースに変換できることに注意してください。EFはナビゲーションプロパティ(例えばHow to use interface properties with CodeFirstを参照)に具体的な型を使用させます。アイテムのNotesコレクションは、コアプロジェクトにはINoteタイプですが、EFプロジェクトにはEfNoteタイプです。 EF6プロジェクトとして

、Iは各タイプ(EfItemEfNote)ためDbSetと及び注意事項、及びDbContext派生クラスを表すPOCOオブジェクトのカップルを追加しました。これらのオブジェクトは、他の具体的な型と直接関係のない単純明快な型であり、しばしば対応するコアインタフェースを実装していないこともあります。たとえば、コアプロジェクトではIItemを実装するItemコンクリート型がありますが、EfItemEfItemList<EfNote> Notesですが、IItemList<INote> Notesです)とは完全に独立しています。継承はなく、テーブルは分かれていません。 EfItemは、SQLテーブルItemにマッピングされ、EfNoteNoteにマッピングされます。ここで

は私のEFオブジェクトにとって必須のコードです:ここでは

public class EfItem 
{ 
    public string Id { get; set; } 
    public string SortId { get; set; } 
    public string ParentId { get; set; } 
    public string Head { get; set; } 
    public short ElementCode { get; set; } 
    public int LegacyNumber { get; set; } 
    public int Flags { get; set; } 
    public string Lemma { get; set; } 
    public short Homograph { get; set; } 
    public string Content { get; set; } 
    public DateTime TimeCreated { get; set; } 
    public string CreatorId { get; set; } 
    public IList<EfNote> Notes { get; set; } 
} 
public class EfNote 
{ 
    public string Id { get; set; } 
    public string ItemId { get; set; } 
    public Item Item { get; set; } 
    public string BookmarkId { get; set; } 
    public string UserId { get; set; } 
    public string Text { get; set; } 
    public byte Level { get; set; } 
    public DateTime TimeCreated { get; set; } 
} 

は私のEFコンテキストです:

protected override void OnModelCreating(DbModelBuilder mb) 
{ 
    mb.Conventions.Remove<PluralizingTableNameConvention>(); 
    // item 
    mb.Entity<EfItem>().ToTable("Item"); 
    mb.Entity<EfItem>().Property(i => i.Id).IsFixedLength().HasMaxLength(32) 
     .IsRequired().IsUnicode(false); 
    mb.Entity<EfItem>().Property(i => i.SortId).HasMaxLength(500) 
     .IsRequired().IsUnicode(false); 
    mb.Entity<EfItem>().Property(i => i.ParentId).IsFixedLength().HasMaxLength(32) 
     .IsUnicode(false); 
    mb.Entity<EfItem>().Property(i => i.Head).HasMaxLength(50).IsUnicode(true); 
    mb.Entity<EfItem>().Property(i => i.ElementCode).IsRequired(); 
    mb.Entity<EfItem>().Property(i => i.LegacyNumber).IsRequired(); 
    mb.Entity<EfItem>().Property(i => i.Flags).IsRequired(); 
    mb.Entity<EfItem>().Property(i => i.Lemma).HasMaxLength(200).IsRequired(); 
    mb.Entity<EfItem>().Property(i => i.Homograph).IsRequired(); 
    mb.Entity<EfItem>().Property(i => i.Content).IsRequired().IsUnicode(true) 
     .HasColumnType("xml"); 
    mb.Entity<EfItem>().Property(i => i.TimeCreated) 
     .IsRequired() 
     .HasColumnType("datetime2"); 
    mb.Entity<EfItem>().Property(i => i.CreatorId).HasMaxLength(100).IsRequired(); 
    // notes 
    mb.Entity<EfNote>().ToTable("Note"); 
    mb.Entity<EfNote>().Property(n => n.Id).IsFixedLength().HasMaxLength(32) 
     .IsRequired().IsUnicode(false); 
    mb.Entity<EfNote>().Property(n => n.ItemId).IsFixedLength().HasMaxLength(32) 
     .IsRequired().IsUnicode(false); 
    mb.Entity<EfNote>().Property(n => n.BookmarkId) 
     .HasMaxLength(50).IsUnicode(false).IsRequired(); 
    mb.Entity<EfNote>().Property(n => n.UserId).HasMaxLength(100).IsRequired(); 
    mb.Entity<EfNote>().Property(n => n.Text).HasMaxLength(2000).IsRequired(); 
    mb.Entity<EfNote>().Property(n => n.Level).IsRequired(); 
    mb.Entity<EfNote>().Property(n => n.TimeCreated).IsRequired() 
     .HasColumnType("datetime2"); 
    base.OnModelCreating(mb); 
} 

SQLテーブルの定義は次のとおりです。あなたのワークコンテキストで

CREATE TABLE [dbo].[Item](
    [Id] [char](32) NOT NULL, 
    [SortId] [varchar](500) NOT NULL, 
    [ParentId] [char](32) NULL, 
    [Head] [nvarchar](50) NULL, 
    [ElementCode] [smallint] NOT NULL, 
    [LegacyNumber] [int] NOT NULL, 
    [Flags] [int] NOT NULL, 
    [Lemma] [nvarchar](200) NOT NULL, 
    [Homograph] [smallint] NOT NULL, 
    [Content] [xml] NOT NULL, 
    [CreatorId] [nvarchar](100) NOT NULL, 
    [TimeCreated] [datetime2](7) NOT NULL, 
CONSTRAINT [PK_Item] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
) 

CREATE TABLE [dbo].[Note](
    [Id] [char](32) NOT NULL, 
    [ItemId] [char](32) NOT NULL, 
    [BookmarkId] [varchar](50) NOT NULL, 
    [UserId] [nvarchar](100) NOT NULL, 
    [Text] [nvarchar](2000) NOT NULL, 
    [Level] [tinyint] NOT NULL, 
    [TimeCreated] [datetime2](7) NOT NULL, 
CONSTRAINT [PK_Note] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
) 
+0

OnModelCreatingだけでなく、完全なコンテキストを含めることができますか? – Fionn

+0

あなたは 'EfNote'に' Item'を持っています。それが原因です。 –

+0

私には恥ずかしいですが、Itemリファレンスがリファクタリングをエスケープしました...ありがとうございました。 Gert、あなたは答えとしてマークすることができるように私の投稿に答えることができますか?少なくとも私はそのような場合の一般的なアプローチを検証できました。私はEF7でもインターフェイスを扱うときは同じであると思います。 – Naftis

答えて

2

。cs

変更 公開DbSet項目{get;セット; } 〜 公開DbSet EFItems {get;セット; 。メソッド保護オーバーライドボイドOnModelCreating(DbModelBuilderのMB)

b.Entity()ToTable( "EFItem")にも}

EFは、 'Item'という名前のクラスを作成しているので、C#クラスとDBテーブル名の間のいくつかの命名規則に従います。私は、EF混合クラスItemとEFItemを一緒に使用します。

関連する問題