簡體   English   中英

實體框架嘗試將SQL中不存在的表用於導航屬性

[英]Entity framework is trying to use a table that doesn't exist in the SQL for a navigation property

在我的C#應用​​程序(一個ASP.NET MVC5網站)中,我使用Entity Framework 6作為我的ORM,並且對現有數據庫使用代碼優先。 該數據庫是SQL Server 2012 Standard。

在我的數據庫中,我有一個視圖(dbo.vBoardReportLayouts),它充當許多不同元素的聯接表。 我已經為此視圖創建了一個實體,並配置了導航屬性。

當我嘗試將此實體與LINQ實體框架一起使用時,會生成一個SQL查詢,該查詢試圖使用實際上不存在的表。 具體來說,它正在尋找BoardReportLayoutPages表。


現在了解所有血腥細節...

vBoardReportLayouts視圖如下所示:

| ReportID | PageTypeId | PageId | LayoutID |
+----------+------------+--------+----------+
| 1        | 1          | 1      | 1        |
| 1        | 1          | 1      | 2        |
| 1        | 1          | 2      | 3        |
| 1        | 1          | 3      | 4        |
| 1        | 2          | 4      | 5        |
| 1        | 2          | 4      | 6        |
| 2        | 1          | 1      | 1        |
| 2        | 1          | 1      | 2        |
| 2        | 1          | 2      | 3        |
| 2        | 1          | 3      | 4        |
| 2        | 2          | 4      | 5        |
| 2        | 2          | 4      | 6        |

BoardReportLayouts實體類:

[Table("vBoardReportLayouts")]
public partial class BoardReportLayout {
    public BoardReportLayout() {
        BoardReports = new HashSet<BoardReport>();
        PageTypes = new HashSet<PageType>();
        Pages = new HashSet<Page>();
        PageLayouts = new HashSet<PageLayout>();
    }

    [Key]
    public int BoardReportLayoutId { get; set; }

    public int BoardReportId { get; set; }

    public int PageTypeId { get; set; }

    public int PageId { get; set; }

    public int PageLayoutId { get; set; }

    public virtual ICollection<BoardReport> BoardReports { get; set; }
    public virtual ICollection<PageType> PageTypes { get; set; }
    public virtual ICollection<Page> Pages { get; set; }
    public virtual ICollection<PageLayout> PageLayouts { get; set; }
}

OnModelCreating()方法中:

modelBuilder.Entity<BoardReportLayout>()
    .HasMany(e => e.BoardReports)
    .WithMany(e => e.BoardReportLayouts);

modelBuilder.Entity<BoardReportLayout>()
    .HasMany(e => e.PageTypes)
    .WithMany(e => e.BoardReportLayouts);

modelBuilder.Entity<BoardReportLayout>()
    .HasMany(e => e.Pages)
    .WithMany(e => e.BoardReportLayouts);

modelBuilder.Entity<BoardReportLayout>()
    .HasMany(e => e.PageLayouts)
    .WithMany(e => e.BoardReportLayouts);

BoardReport,PageType,Page和PageLayout實體均定義了以下屬性:

public virtual ICollection<BoardReportLayout> BoardReportLayouts { get; set; }

執行此LINQ查詢:

var test = (from l in ppdb.BoardReportLayouts
            where l.BoardReportId == 8
            select l.Pages).SelectMany(p => p).ToList();

生成此SQL:

SELECT [Join1].[PageId] AS [PageId], 
    [Join1].[PageTypeId] AS [PageTypeId], 
    [Join1].[Name] AS [Name], 
    [Join1].[ParameterValue] AS [ParameterValue], 
    [Join1].[SsrsPageParamterValue] AS [SsrsPageParamterValue], 
    [Join1].[TableOfContentsOrder] AS [TableOfContentsOrder]
    FROM  [dbo].[vBoardReportLayouts] AS [Extent1]
    INNER JOIN  (
    SELECT [Extent2].[BoardReportLayout_BoardReportLayoutId] AS [BoardReportLayout_BoardReportLayoutId],
        [Extent3].[PageId] AS [PageId],
        [Extent3].[PageTypeId] AS [PageTypeId],
        [Extent3].[Name] AS [Name],
        [Extent3].[ParameterValue] AS [ParameterValue],
        [Extent3].[SsrsPageParamterValue] AS [SsrsPageParamterValue],
        [Extent3].[TableOfContentsOrder] AS [TableOfContentsOrder]
        FROM  [dbo].[BoardReportLayoutPages] AS [Extent2]
        INNER JOIN [dbo].[Pages] AS [Extent3] ON [Extent3].[PageId] = [Extent2].[Page_PageId]
    ) AS [Join1] ON [Extent1].[BoardReportLayoutId] = [Join1].[BoardReportLayout_BoardReportLayoutId]
    WHERE 8 = [Extent1].[BoardReportId]

問題出在[Join1]表表達式的FROM子句中。 我不確定為什么要嘗試使用表dbo.BoardReportLayoutPages因為它可以直接從視圖連接到Pages表。 dbo.BoardReportLayoutPages不存在,因此將引發異常。

此代碼段指定BoardReportLayout與頁面具有多對多關系:

modelBuilder.Entity<BoardReportLayout>()
    .HasMany(e => e.Pages)
    .WithMany(e => e.BoardReportLayouts);

這意味着應該有一個BoardReportLayoutPages表來對該關系進行建模。 視圖支持BoardReportLayout ,因此您必須編寫sql BoardReportLayout創建它,因為代碼首先會生成表以支持您在此處定義的模型。 如果您在此處確實具有多對多關系,那么您還應該將BoardReportLayoutPages創建為表或視圖。

但您在BoardReportLayout也有一個PageId屬性。 這意味着PageBoardReportLayout之間存在第二對多關系。 如果要通過這種關系BoardReportLayoutPage ,則應添加一個public Page Page { get; set; } public Page Page { get; set; } public Page Page { get; set; }導航屬性。

只有您可以決定這里是否有兩個關系,或者只有一個,以及您具有什么類型的關系。

暫無
暫無

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

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