视图和实体框架数据不对?
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<VJOBS2> list = new List<VJOBS2>()
- 是无用的,因为下一行将创建的列表扔进垃圾中,创建新的列表 (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
【讨论】:
以上是关于视图和实体框架数据不对?的主要内容,如果未能解决你的问题,请参考以下文章