【问题标题】:Entity Framework returns incorrect data from SQL Server view实体框架从 SQL Server 视图返回不正确的数据
【发布时间】: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

我看不出什么可以改变数据。有没有像记录回收这样的东西来获得更好的性能?

【问题讨论】:

    标签: sql-server entity-framework view


    【解决方案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))

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多