视图和实体框架数据不对?

Posted

技术标签:

【中文标题】视图和实体框架数据不对?【英文标题】:View and Entity Framework data not right? 【发布时间】:2014-11-27 06:18:53 【问题描述】:

当我从 SQL Server Management Studio 中的视图中选择时,我从某个表中获得了一个视图,它工作正常,但是当我使用实体框架从视图中获取数据时,它就不同了。

ReturnDbForTesEntities1 db = new ReturnDbForTesEntities1();
List<VJOBS2> list = new List<VJOBS2>();
list = db.VJOBS2.ToList();

记录数相同,但最后 2 行不同。

我有求职申请表,可以申请2个或更多的工作

ApplicantId    ApplicantName  JobId  JobName
   1              Mohamed       1    Developer
   1              Mohamed       2    IT Supporter 

但在列表中

ApplicantId    ApplicantName  JobId  JobName
   1              Mohamed       1    Developer
   1              Mohamed       1    Developer

【问题讨论】:

信息不足以帮助您。至少,显示表定义、视图定义、SSMS 中正在执行的 SQL 查询。此外,这 - List&lt;VJOBS2&gt; list = new List&lt;VJOBS2&gt;() - 是无用的,因为下一行将创建的列表扔进垃圾中,创建新的列表 (ToList),并将新的 lit 分配给 list 变量。 【参考方案1】:

从实体框架中使用时,views 存在一个微妙的问题。

如果您有一个表,请务必将其与 EF 一起使用,您需要有一个主键来唯一标识每一行。通常,这是一个单列,例如ID 或类似的东西。

对于视图,您没有“主键”的概念 - 视图仅包含来自某些表的一些列。

因此,当 EF 映射视图时,它找不到主键 - 因此,它将使用视图中的所有不可为空的列作为“替代”主键。

我不知道在你的情况下这些是什么 - 你应该能够从 .edmx 模型中分辨出来。

假设(ApplicantId, ApplicantName) 是 EF 现在用作“替代”主键的两个不可为空的列。当 EF 去读取数据时,它将读取第一行 (1, Mohamed, 1, Developer) 并为此创建一个对象。

当 EF 读取第二行 (1, Mohamed, 2, IT-Supporter) 时,它注意到“主键”(1, Mohamed) 与以前相同 - 所以它不会费心创建一个读取这些值的新对象,但主键是相同,因此它必须是之前已经读取过的对象,所以它使用那个对象。

所以问题真的是你不能在视图上有明确的主键。

您可以调整您的 EF 模型以使 EF 清楚,例如(ApplicantId, JobId) 确实是主键(您需要确保这些列都不可为空) - 或者您需要在视图中添加类似“人工”主键的内容:

CREATE VIEW dbo.VJOBS2
AS
   SELECT 
       ApplicantId, ApplicantName, JobId, JobName,
       RowNum = ROW_NUMBER() OVER(ORDER BY JobId)
   FROM
       dbo.YourBaseTable

通过将 RowNum 列添加到您的视图中,该列仅对行进行编号 1, 2, ...., n,您将获得一个新的、不可为空的列,EF 将其包含在“替代 PK”中,并且由于这些数字是连续的,因此不会两行将具有相同的“PK”值,因此不会错误地被已从数据库中读取的内容替换。

【讨论】:

谢谢我明白了:)【参考方案2】:

仅供参考,我必须添加 ISNULL 才能让它为我工作,请参阅此代码示例第一行中的修改:

SELECT ISNULL(ROW_NUMBER() OVER(ORDER BY a.OrderItemID),0) as ident, a.* 
FROM
(
      SELECT e.AssignedMachineID, e.StartDate, e.OrderItemID, e2.OrderItemID AS doubleBookedEventID, e.StartTime, e.EndTime, e2.StartTime AS doubleBookedStartDateTime, e2.EndTime AS doubleBookedEndDateTime, DATEDIFF(MINUTE,e2.StartTime,e.EndTime) AS doubleBookedMinutes
  FROM schedule e
    INNER JOIN schedule e2
      ON e.AssignedMachineID = e2.AssignedMachineID
      and e.StartDate=e2.StartDate
      AND e.schedID <> e2.schedID
      AND e2.StartTime BETWEEN DATEADD(minute,1,e.StartTime) AND DateAdd(minute,-1,e.EndTime) where  Coalesce(e.ManuallyOverrided,0)=0 and Coalesce(e.AssignedMachineID,0) > 0
      ) a

【讨论】:

以上是关于视图和实体框架数据不对?的主要内容,如果未能解决你的问题,请参考以下文章

视图和实体框架

实体框架 - Linq 中的数据库视图或连接到实体

实体框架和 SQL Server 视图

如何使用实体框架测试视图?

实体框架显示多个同一行

实体框架中联合数据“视图”上的 OData