In my C# application (an ASP.NET MVC5 website) I am using Entity Framework 6 as my ORM and I'm using code-first with an existing database. The database is SQL Server 2012 Standard.
In my database I have a view (dbo.vBoardReportLayouts) that functions as a joining table for a number of different elements. I've created an entity for this view and configured the navigation properties.
When I attempt to use this entity with LINQ entity framework generates a SQL query that tries to use a table that doesn't actually exist. Specifically it is looking for the BoardReportLayoutPages
table.
The vBoardReportLayouts view looks like this:
| 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 |
The BoardReportLayouts entity class:
[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; }
}
From the OnModelCreating()
method of the dbContext:
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);
The BoardReport, PageType, Page, and PageLayout entities all have the following property defined:
public virtual ICollection<BoardReportLayout> BoardReportLayouts { get; set; }
Executing this LINQ query:
var test = (from l in ppdb.BoardReportLayouts
where l.BoardReportId == 8
select l.Pages).SelectMany(p => p).ToList();
Generates this 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]
The problem is in the FROM
clause of the [Join1]
table expression. I'm not sure why it is trying to use the table dbo.BoardReportLayoutPages
since it could join directly from the view to the Pages
table. The table dbo.BoardReportLayoutPages
doesn't exist so this throws an exception.
This bit of code is specifying that the BoardReportLayout
has a many to many relationship with pages:
modelBuilder.Entity<BoardReportLayout>()
.HasMany(e => e.Pages)
.WithMany(e => e.BoardReportLayouts);
That means there should be a BoardReportLayoutPages
table to model that relationship. The BoardReportLayout
is supported by a view, so you had to write the sql to create it yourself, because code first would have generated tables to support the model you have defined here. If you do have a many-to-many relationship here, then you should have created the BoardReportLayoutPages
as a table or view also.
But you also have a PageId
property in the BoardReportLayout
. This means that there is a second one-to-many relationship between a Page
and BoardReportLayout
s. If you want to get to a BoardReportLayout
's Page
via this relationship then you should add a public Page Page { get; set; }
public Page Page { get; set; }
public Page Page { get; set; }
navigation property.
Only you can decide whether you have two relationships here, or just one, and what type of relationship(s) you have.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.