简体   繁体   中英

IEnumerable<T> somehow gets transformed to EntitySet<T>

I have an hierarchy of classes that I fetch from database by LINQ to SQL controller and the display that big class as needed.Let me explain:

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


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


Comment
//...some generic types

So in my controller I fetch big product and pass it to main view, then pass reviews in foreach to partial views and in each of these partial views I have another foreach that should list all comments as partial view.

The types are defined clear as Ienumerable in classes and this dll worked fine with web forms,now when I hover my mouse over Comment in foreach loop in razor it says it's EntitySet instead of IEnumerable and I get "null exception: acessed context after disposed", that was the reason I am passing it as IEnumerable in first place as I fetch everything in one place. What could be the reason for such behaviour? I didn't change anything in this dll that used to work fine with webforms.

UPDATE: As I mentioned it worked fine with WebForms, I am calling .ToList() to get IEnumerable from IQueryable in when selecting data!

Just because you declare it as IEnumerable<T> , that doesn't change the execution-time type. So when you pass it over to your view, the view would know at compile-time that it's IEnumerable<T> but when you hover over it when debugging, you'll see the actual type. (It's not clear at what point you were hovering over Comment in the razor view, but I strongly suspect it's in the middle of a debugging session.)

If you want to take a copy of the data so that you can dispose the context, just call ToList() and return the result - that will be a List<T> instead.

Note that this compile-time/execution-time difference has nothing to do with LINQ or MVC really. You can see the same thing extremely easily without anything complicated:

object value = "hello";

The compile-time type of value is object , which will stop you calling Substring etc on it. But if you hover over value in a debugging session (or look at it in the Watch or Local window) you'll see that the execution-time type is still string .

EDIT: From your edit:

I am calling .ToList() to get IEnumerable from IQueryable in when selecting data!

I'd really like to see that code, because I don't believe you're simply using something like:

return query.ToList();

If you're returning the result of calling ToList() , that won't be an EntitySet .

When you return a reference to an interface type, like IEnumerable<T> , the reference still points to the object whose run-time type implements the interface. More generally, whenever you refer to an object through an interface that it implements, or through a base class in its inheritance chain, you're still referring to an instance of the object's most-derived type.

For example:

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());

Output:

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

If you want to copy the data to another object that also implements IEnumerable<T> , you need to write some code to do that. As others have suggested, calling ToList() is an easy way to achieve this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM