在LINQ中使用Projection代替Find()

时间:2017-01-31 15:26:27

标签: c# asp.net-mvc linq

相对较新的MVC和LINQ。

使用LINQ / EF的内置方法通常不适合我,因为我'需要使用多个表并创建一个新类型的投影以获取我需要的数据。

当返回iEnumerable时,我能够毫无问题地执行此操作。我的观点是期待iEnumerable和我的LINQ查询提供了这个。

但是,当我尝试替换Find()方法以返回单个记录时,我遇到了问题。

我的投影与返回多条记录的投影相同,但我添加了一个where子句来限制返回单个记录(使用唯一ID)。

我已经改变了我的观点,期望和我投射的类型的对象,但这是我能得到的。

如果我只是按原样返回查询,延迟执行会导致一个问题,即我实际上将查询传递给了我的视图,而不是结果(如预期的那样)。

所以我试图找出如何(我猜)执行查询并获取控制器中的对象,然后将其传递给视图。我已经尝试过SingleOrDefault()之类的“强迫”。执行但是会生成一个新的异常(无法创建类型' System.Object'的常量值。在此上下文中仅支持基本类型或枚举类型。)

显然,我不明白这里发生的事情。

        var model =
            (from p in db.t_Protocol
            join pt in db.t_ProtocolType on p.ProtocolTypeId equals pt.ProtocolTypeID
            where p.ProtocolId.Equals(id)
            select new ProtocolView
            {
                ProtocolId = p.ProtocolId,
                Protocol = p.Protocol,
                ProtocolType = pt.ProtocolType,
                IsAdmission = p.IsAdmission,
                IsReleased = p.IsReleased
            })
            ;

我的观点是:     @model ECM.Models.ProtocolView

1 个答案:

答案 0 :(得分:0)

首先,通过声明您的视图期望@model ECM.Models.ProtocolView表示该视图仅期望单个记录。如果在设置Var模型时子表有多于1条记录,那么无论父级只有1条记录,您的投影都会强制n条记录进入模型。为了让你的视图期望一个IEnumerable你需要将你的视图声明更改为@model IEnmerable<ECM.Models.ProtocolView>另外如果你真的需要先执行一次Find use IQueryable,它们会将结果作为IEnumerable返回,因为Ienumerable上的有效负载小于IQueryable