簡體   English   中英

EF6:“實體類型不能共享表”錯誤,沒有任何表拆分

[英]EF6: “entity types cannot share table” error without any table splitting

我創建了一個 EntityFramework 6 數據上下文(代碼優先)來表示數據庫中的一些表:至於下面引用的重現代碼,一個( Items )包含某種字典的項目,另一個( Notes )包含一些可以附在物品上。 一個項目可以包含 0 個或多個注釋。 這里沒有什么困難:我將為每個表只有 1 個 POCO 對象,這就是我正在做的; 然而,當從我的DbContext初始化數據庫時,我收到錯誤:

"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 表的情況,此錯誤似乎很有意義,但這里的情況並非如此。 對於每個表,我只有 1 個且只有 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 項目,我添加了幾個 POCO 對象來表示項目和注釋,以及一個DbContext派生類,每個類型都有一個DbSetEfItemEfNote )。 請注意,這些對象是簡單的、具體的類型,與任何其他具體類型都沒有直接關系,而且通常它們甚至沒有實現相應的核心接口。 例如,在核心項目中,我有一個Item具體類型實現IItem ,但它完全獨立於EfItemEfItemList<EfNote> NotesIItemList<INote> Notes )。 沒有繼承,也沒有分表; EfItem映射到 SQL 表ItemEfNoteNote

這是我的 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
)

在您的 WorkContext.cs 中

改變

public DbSet<EfItem> Items { get; set; }

public DbSet<EfItem> EFItems { get; set; }

也在方法

protected override void OnModelCreating(DbModelBuilder mb)

b.Entity<EfItem>().ToTable("EFItem");

EF 遵循 C# 類和 DB 表名之間的一些命名約定,因為您創建了一個名為“Item”的類,恐怕 EF 將類 Item 和 EFItem 混合在一起。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM