视图和实体框架数据不正确
本文关键字:数据 不正确 框架 实体 视图 | 更新日期: 2023-09-27 18:32:15
当我从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
从实体框架使用视图时存在一个微妙的问题。
如果你有一个表,请将其与 EF 一起使用,你需要有一个主键来唯一标识每一行。通常,这是单个列,例如ID
或类似的东西。
对于视图,您没有"主键"的概念 - 视图只包含某些表中的一些列。
因此,当 EF 映射视图时,它找不到主键 - 因此,它将使用视图中所有不可为空的列作为"替代"主键。
我不知道这些在你的情况下是什么 - 你应该能够从.edmx
模型中看出来。
假设 EF 现在用作"替代"主键的两个不可为空的列(ApplicantId, ApplicantName)
。当 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"值,因此不会错误地将任何行替换为已从数据库中读取的内容。
仅供参考,我必须添加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