IEnumerable <t>以某种方式转换为EntitySet <t> </t> </t>

时间:2012-03-28 17:40:22

标签: c# asp.net linq-to-sql asp.net-mvc-4

我有一个类的层次结构,我通过LINQ to SQL控制器从数据库中获取,并根据需要显示大类。让我解释一下:

BigProduct
IEnumerable<Review>
//...some generic types


Review
IEnumerable<Comment>
//...some generic types


Comment
//...some generic types

因此,在我的控制器中,我获取大型产品并将其传递给主视图,然后将foreach中的评论传递给部分视图,并且在每个部分视图中,我有另一个foreach,应该将所有注释列为部分视图。

这些类型在类中明确定义为Ienumerable,这个dll在Web表单中运行良好,现在当我将鼠标悬停在razor的foreach循环中的Comment时,它说它是EntitySet而不是IEnumerable,我得到“null异常:acessed context处理后“,这就是我将它作为IEnumerable传递给我的原因,因为我在一个地方取了所有东西。这种行为可能是什么原因?我没有改变过去在webforms上工作的dll中的任何内容。

更新:正如我所提到的,它在WebForms中运行良好,我在选择数据时调用.ToList()从IQueryable中获取IEnumerable!

2 个答案:

答案 0 :(得分:9)

仅仅因为声明为IEnumerable<T>,这不会改变执行时间类型。因此,当您将视图传递给视图时,视图将在编译时知道它是IEnumerable<T>,但是当您在调试时将鼠标悬停在它上面时,您将看到实际类型。 (目前尚不清楚你在剃须刀视图中在Comment处悬停的时间点,但我强烈怀疑它正处于调试会话的中间。)

如果您想要获取数据的副本以便处理上下文,只需致电ToList()并返回结果 - 而不是List<T>

请注意,此编译时/执行时间差异与LINQ或MVC无关。你可以非常轻松地看到同样的东西而不会有任何复杂的事情:

object value = "hello";

value编译时类型为object,这将阻止您在其上调用Substring等。但是如果你将鼠标悬停在value的调试会话中(或者在Watch或Local窗口中查看它),你会发现执行时类型仍然是string

编辑:从你的编辑:

  

我在选择数据时调用.ToList()从IQueryable获取IEnumerable!

我真的很想看到这些代码,因为我不相信你只是使用类似的东西:

return query.ToList();

如果您要返回调用ToList()的结果,那么将不会成为EntitySet

答案 1 :(得分:2)

当您返回对接口类型的引用(如IEnumerable<T>)时,引用仍指向运行时类型实现接口的对象。更一般地说,无论何时通过它实现的接口或通过其继承链中的基类引用对象,您仍然指的是该对象的派生类型最多的实例。

例如:

object o1 = new object();
object o2 = "I am a string.";
object o3 = 42;

Console.WriteLine(o1.GetType());
Console.WriteLine(o2.GetType());
Console.WriteLine(o3.GetType());

IComparable ic1 = "I am a string.";
IComparable ic2 = 42;

Console.WriteLine(ic1.GetType());
Console.WriteLine(ic2.GetType());

输出:

System.Object
System.String
System.Int32
System.String
System.Int32

如果要将数据复制到另一个也实现IEnumerable<T>的对象,则需要编写一些代码来执行此操作。正如其他人所建议的那样,调用ToList()是实现这一目标的一种简单方法。