渲染视图时 foreach 出现奇怪的空引用错误
这个错误太奇怪了,我真的无法弄清楚到底出了什么问题!
在 UserController 中,
public virtual ActionResult Index()
{
var usersmdl = from u in RepositoryFactory.GetUserRepo().GetAll()
select new UserViewModel
{
ID = u.ID,
UserName = u.Username,
UserGroupName = u.UserGroupMain.GroupName,
BranchName = u.Branch.BranchName,
Password = u.Password,
Ace = u.ACE,
CIF = u.CIF,
PF = u.PF
};
if (usersmdl != null)
{
return View(usersmdl.AsEnumerable());
}
return View();
}
我的视图类型为 @model IEnumerable
位于顶部。
发生的情况是这样的:
到底在哪里以及什么是 null!?
我使用最小起订量从一个假存储库创建用户。我还编写了通过的单元测试,以确保返回适量的模拟用户。
也许有人可以在这里指出我正确的方向?堆栈跟踪的顶部是:
at lambda_method(Closure , User )
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at ASP.Index_cshtml.Execute()
这与 linq 有关吗?告诉我是否应该包含完整的堆栈跟踪。
编辑
哇,我不敢相信这是 u.UserGroupMain.GroupName
,谢谢 @Lunivore。
这是一个模型存储库,我进行了单元测试来检查模拟存储库用户是否具有 UserGroupMain 的模拟实例,但我没有断言 wee 属性 GroupName
已经设定了!
感谢@RPM1984,您建议获取代码来破坏控制器本身。另外我学到了一些新东西。
谢谢@Mikael,我第一次使用
我猜你生活、编码和学习!
This error is so weird I Just can't really figure out what is really wrong!
In UserController I have
public virtual ActionResult Index()
{
var usersmdl = from u in RepositoryFactory.GetUserRepo().GetAll()
select new UserViewModel
{
ID = u.ID,
UserName = u.Username,
UserGroupName = u.UserGroupMain.GroupName,
BranchName = u.Branch.BranchName,
Password = u.Password,
Ace = u.ACE,
CIF = u.CIF,
PF = u.PF
};
if (usersmdl != null)
{
return View(usersmdl.AsEnumerable());
}
return View();
}
My view is of type @model IEnumerable<UserViewModel>
on the top.
This is what happens:
Where and what exactly IS null!?
I create the users from a fake repository with moq. I also wrote unit tests, which pass, to ensure the right amount of mocked users are returned.
Maybe someone can point me in the right direction here? Top of the stack trace is :
at lambda_method(Closure , User )
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at ASP.Index_cshtml.Execute()
Is it something to do with linq here? Tell me If I should include the full stack trace.
Edit<BangsHeadOnWall />
Wow, I cannot believe it was u.UserGroupMain.GroupName
thanks @Lunivore.
It was a mockup repo, and I had a unit test to check if the mock repo user had a mock instance of UserGroupMain but I didn't Assert if the wee property GroupName
had been set!
Thanks @RPM1984 you're suggestion got the code to break in the controller itself. Plus I learnt something new.
Thanks @Mikael, first time I used the immediate window wow its cool! =D
Guess you live, code and learn!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,它与 linq 有关。在您使用查询之前,Linq 不会执行该查询。因此,当您循环遍历它时,查询就会运行,但由于某种原因它会崩溃。
GetAll 返回什么?您可以做的一件事是在 Index() 内放置一个断点,当它中断时,将其写入立即窗口中。
如果你找不到立即窗口,你可以通过
在 findbox(VS 顶部)中
写入来打开它。如果这没有崩溃,问题可能出在 Index() 内的 linq 中。据我所知,我怀疑 u.UserGroupMain 或 u.Branch 为空。但如果没有更多信息,很难说。
Yeah, it got something to do with linq. Linq doesn't execute the query before you use it. So when you loop over it the query is run and for some reason it crashes.
What is GetAll returning? One thing you could do is to place a breakpoint inside Index() and when it breaks write this in the immediate window.
If you can't find the Immediate window you can open it by writing
in the findbox(in the top of VS)
If that doesn't crash the problem is probably in the linq inside Index(). From what I can see I would suspect that u.UserGroupMain or u.Branch is null. But hard to tell without more info.
将此行更改
为:
为什么?
来自 MSDN:
英语 - 因为
.AsEnumerable()
转换为IEnumerable
,但IQueryable
已经 实现IEnumerable
,因此查询没有被具体化,并且当您枚举foreach
中的项目时,查询会在视图中延迟计算。 LINQ 延迟执行的经典技巧。这就是我喜欢 Resharper 的原因 - 它会告诉您 AsEnumerable() 调用是多余的 - 然后您的查询被推迟就会变得更加明显。
.ToList()
将在到达视图之前触发查询,并且仍然实现IEnumerable
,因此您的模型绑定不需要更改。Change this line:
To this:
Why?
From MSDN:
In English - Because
.AsEnumerable()
converts toIEnumerable<T>
, butIQueryable<T>
already implementsIEnumerable<T>
, so the query is not being materialized - and is being lazily evaluated in the View when you enumerate the items in theforeach
. Classic trick of LINQ deferred execution.This is why i love Resharper - it will tell you the
AsEnumerable()
call is redundant - then it will become much more obvious your query is being deferred..ToList()
will fire the query before it gets to the View, and still implementsIEnumerable<T>
so your model binding need not change.检查您在用户中设置的
UserGroupMain
和Branch
是否不为空:如果这解决了您的问题,Mikael 的答案解释了为什么会发生这种情况,而不是进一步在查询中。
Check that the
UserGroupMain
andBranch
you've set up in your users aren't null:If that fixes your problem, Mikael's answer explains why it was happening there and not further up in the query.