IEnumerable <T> somehow converts to EntitySet <T>

I have a class hierarchy that I retrieve from a database using a LINQ to SQL controller and display this large 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 a large product and pass it to the main view, then I pass the views to the foreach for the partial views, and in each of those partial views, I have another foreach that should render all comments as a partial view.

The types are defined as Ienumerable in classes and this dll works fine with web forms, now when I hover over the comment in the foreach loop in razor it says EntitySet instead of IEnumerable and I get "null exception: acessed context after of how it was set ", which is why I am passing it as IEnumerable in the first place, since I am taking everything in one place. What could be the reason for this behavior? I didn't change anything in this DLL which worked fine with web forms.

UPDATE: As I said, it works great with WebForms, I am .ToList()

calling to get IEnumerable from IQueryable on data selection!

+3


source to share


2 answers


When you return a reference to an interface type, for example IEnumerable<T>

, that reference still points to an object whose execution type implements the interface. More generally, whenever you refer to an object through an interface that it implements, or through a base class in your inheritance chain, you are still referring to an instance of the most derived object.

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 data to another object that also implements IEnumerable<T>

, you need to write code to do this. As others have suggested, challenge ToList()

is an easy way to achieve this.

+2


source


Just because you declare it as IEnumerable<T>

, which doesn't change the execution type. So when you pass it to your view, the view will know at compile time what it is IEnumerable<T>

, but when you hover it over yourself while debugging, you will see the actual type. (It's not clear at what point you hovered over Comment

in razor mode, but I strongly suspect it in the middle of a debugging session.)

If you want to take a copy of the data so you can get rid of the context, just call ToList()

and return the result - it will instead List<T>

.

Please note that this compile / runtime difference has nothing to do with LINQ or MVC. You can see the same thing very easily without anything complicated:

object value = "hello";

      

The compile-time type value

is object

, which will prevent you from calling Substring

etc. But if you hover over value

in the debug session (or look at it in the Clock or Local Window), you will see that the run type is still string

.



EDIT: From your edit:

I call .ToList () to get an IEnumerable from an IQueryable when I select data!

I'd love to see this code because I don't believe you are just using something like:

return query.ToList();

      

If you return the result of the call ToList()

, it won't EntitySet

.

+9


source







All Articles