实体框架从 SQL Server 视图返回不正确的数据
Posted
技术标签:
【中文标题】实体框架从 SQL Server 视图返回不正确的数据【英文标题】:Entity Framework returns incorrect data from SQL Server view 【发布时间】:2017-10-27 03:26:37 【问题描述】:我有一个包含视图的 SQL Server 数据库。
当我执行这个查询时:
select *
from HistoryListingView
order by RequestTime desc`
我得到这个结果:
但是,在我的控制器中(在 ASP.NET MVC 应用程序中),我只执行以下代码:
return Ok(_db.HistoryListingViews.OrderByDescending(r => r.RequestTime));
而且接收到的数据不对应;更准确地说,第 2 行和第 4 行中的 DataType
列不正确,所有其他列似乎都是正确的。
[
"dataType":"Type de stationnement",
"actionType":"Obtenir plusieurs entrées",
"requestTime":"2017-10-26T23:06:43.81",
"username":"admin",
"jsonParameters":"[]",
"error":null,
"userSessionRequestErrorId":null
,
"dataType":"Type de stationnement",
"actionType":"Obtenir plusieurs entrées",
"requestTime":"2017-10-26T23:06:43.81",
"username":"admin",
"jsonParameters":"[]",
"error":null,
"userSessionRequestErrorId":null
,
"dataType":"Local",
"actionType":"Obtenir plusieurs entrées",
"requestTime":"2017-10-26T23:06:42.687",
"username":"admin",
"jsonParameters":"[]",
"error":null,
"userSessionRequestErrorId":null
,
"dataType":"Local",
"actionType":"Obtenir plusieurs entrées",
"requestTime":"2017-10-26T23:06:42.687",
"username":"admin",
"jsonParameters":"[]",
"error":null,
"userSessionRequestErrorId":null
]
我的上下文配置了禁用的lazyLoading 和禁用的ProxyCreation,而我的JsonFormatter (Newtonsoft) 正在使用基本设置:
CamelCasePropertyNamesContractResolver
和
ReferenceLoopHandling.Ignore
我看不出什么可以改变数据。有没有像记录回收这样的东西来获得更好的性能?
【问题讨论】:
【参考方案1】:从实体框架中使用时,views 存在一个微妙的问题。
如果您有表,请务必将其与 EF 一起使用,您需要有一个主键来唯一标识每一行。通常,这是一个单列,例如ID
或类似的东西。
对于视图,您没有“主键”的概念 - 视图仅包含来自某些表的一些列。
因此,当 EF 映射视图时,它找不到主键 - 因此,它将使用视图中的所有不可为空的列作为“替代”主键。
我不知道在你的情况下这些是什么 - 你应该能够从 .edmx
模型或从数据库生成的代码类中分辨出来。
查看您的数据,我假设 RequestTime
是您视图中唯一的不可为空的列。 EF 现在将假定这是该视图的“替代”主键。当 EF 去读取数据时,它将读取第一行(“Type de stationnement”)并为那个。
当 EF 读取第二行时,RequestTime
是相同,因此替代“主键”(RequestTime
)与以前相同 - 所以它不会打扰创建读取了这些值的新对象,但主键相同,因此它必须与之前已读取的对象相同,因此它使用该对象。
所以问题真的是你不能在视图上有明确的主键。
您可以调整 EF 模型以使 EF 清楚主键是什么(您需要确保这些列不可为空) - 或者您需要添加类似您视图的“人工”主键:
CREATE VIEW dbo.HistoryListingView
AS
SELECT
(all the columns you already have in your view),
RowNum = ROW_NUMBER() OVER(ORDER BY SomeValue)
FROM
dbo.YourBaseTable
通过将 RowNum
列添加到您的视图中,该列仅对第 1、2、...、n 行进行编号,您将获得一个新的、不可为空的列,EF 将其包含在“替代 PK”中,并且由于这些数字是连续的,因此不会有两行具有相同的“PK”值,因此不会错误地被已从数据库中读取的内容替换。
【讨论】:
【参考方案2】:感谢@marc_s 的回答,但是
这对我不起作用,因为 RowNum
仍然可以为空
但是,当我添加 ISNULL(ROW_NUMBER() OVER(ORDER BY SomeValue))
时
【讨论】:
以上是关于实体框架从 SQL Server 视图返回不正确的数据的主要内容,如果未能解决你的问题,请参考以下文章
带有实体框架和 SQL Server 数据库的 ASP.NET MVC - 图像未显示在视图中......错误显示“无法将“字节”转换为“字符串”