想要在cshtml中使用公共类的对象,但是遇到了运行时错误:LINQ to Entities中仅支持无参数构造函数和初始值设定项.以下陈述有什么问题?谢谢你的帮助!
@foreach (var obj in ViewData["IncompleteList"] as IEnumerable<Games.TeamAction>)
Run Code Online (Sandbox Code Playgroud)
控制器填充ViewBag,就像
IEnumerable<TeamAction> incomplete = dbIncAct.IncompleteActivity.Where(a => a.activityID == id)
.Select(s => new TeamAction(s.teamID, s.name, id, s.type));
ViewBag.IncompleteList = incomplete;
Run Code Online (Sandbox Code Playgroud)
TeamAction类(命名空间游戏的一部分)非常简单:
public class TeamAction
{
public TeamAction()
{
}
....
public int teamID {get; set;}
public string teamName { get; set; }
public int activityID { get; set; }
public int actionType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
一旦你弄清楚如何解释它,答案就在错误信息中.
您正在创建一个IEnumerable
via LINQ to Entities(实体框架LINQ提供程序),如下所示:
IEnumerable<TeamAction> incomplete = dbIncAct.IncompleteActivity
.Where(a => a.activityID == id)
.Select(s => new TeamAction(s.teamID, s.name, id, s.type));
Run Code Online (Sandbox Code Playgroud)
请注意,您的Select
调用包含一个lambda表达式,该表达式调用带有TeamAction
4个参数的构造函数.一旦你要求第一个元素IEnumerable
,LINQ就会尝试执行你的查询.此时,它会解析您的lambda表达式并尝试将其转换为可以运行的实体框架查询.但是,正如异常消息所说:
Only parameterless constructors and initializers are supported
Run Code Online (Sandbox Code Playgroud)
您不能在LINQ查询中包含参数化构造函数,因为LINQ to Entities不知道如何执行它.要解决此问题,您有几个选择.
选项一:IQueryable - > IEnumerable
最简单的方法是确保EF LINQ提供程序永远不会看到有问题的lambda,因为它会在它到达之前强制IQueryable
进入IEnumerable
.dbIncAct.ImcompleteActivity
可能是a DbSet<>
,并DbSet<>.Where
返回IQueryable
仍依赖于LINQ 2实体的内容.要打破这种依赖性,你可以这样做:
IEnumerable<TeamAction> incomplete = dbIncAct.IncompleteActivity
.Where(a => a.activityID == id)
.AsEnumerable()
.Select(s => new TeamAction(s.teamID, s.name, id, s.type));
Run Code Online (Sandbox Code Playgroud)
这将强制您的EF查询在部件中运行Where
并返回可枚举的IncompleteActivity
实体集合.那个东西(一些内部定义List
的对象)然后用来调用Select
,完全不同于EF.
这里的缺点是你迫使EF查询(可能会命中数据库)立即发生.如果您不想这样,您唯一的选择是使用其他两个选项中的一个来消除参数化构造函数.
选项二:对象初始化器
根据构造函数的作用,您可能也可能无法轻松修复它.如果您的构造函数只是在新创建的对象上设置属性,那么您很幸运.C#引入了新的对象初始化器语法,以便与LINQ和lambdas一起使用,正是出于这个原因:
IEnumerable<TeamAction> incomplete = dbIncAct.IncompleteActivity
.Where(a => a.activityID == id)
.Select(s => new TeamAction
{
TeamId = s.teamID,
Name = s.name,
Id = id,
Type = s.type
});
Run Code Online (Sandbox Code Playgroud)
方案三:重构
如果你的构造函数做了任何实际的工作,那么你需要做一些重构.尝试尽可能多地将逻辑移动到默认TeamAction()
构造函数中.您也可以将一些逻辑放入属性设置器中,尽管您应该尽可能地尽量减少这些逻辑.
如果你的对象确实需要一些复杂的初始化,那么典型的模式就是在生命周期的早期调用初始化方法,例如:
var x = new X { ... };
x.InitializeMe();
Run Code Online (Sandbox Code Playgroud)
例如,您可以在@for
循环内执行此操作,也可以在创建查询后立即执行单独的步骤.
归档时间: |
|
查看次数: |
680 次 |
最近记录: |