IEnumerable <T>каким-то образом преобразуется в EntitySet <T> - PullRequest
3 голосов
/ 28 марта 2012

У меня есть иерархия классов, которую я извлекаю из базы данных с помощью LINQ to SQL controller и отображаю этот большой класс по мере необходимости. Позвольте мне объяснить:

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


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


Comment
//...some generic types

Таким образом, в моем контроллере я выбираю большой продукт и передаю его в основной вид, затем передаю обзоры в foreach частичным представлениям, и в каждом из этих частичных представлений у меня есть другой foreach, который должен перечислять все комментарии как частичное представление.

Типы определены как Ienumerable в классе как понятные как Ienumerable, и эта dll отлично работала с веб-формами. Теперь, когда я наводю указатель мыши на цикл Comment в цикле foreach в бритве, он говорит, что это EntitySet вместо IEnumerable, и я получаю нулевое исключение: доступный контекст после утилизации », именно поэтому я передаю его как IEnumerable на первом месте, так как я получаю все в одном месте. Что может быть причиной такого поведения? Я не изменил ничего в этой dll, которая нормально работала с веб-формами.

ОБНОВЛЕНИЕ: Как я уже говорил, с WebForms все работало нормально, я звоню .ToList(), чтобы получить IEnumerable из IQueryable при выборе данных!

Ответы [ 2 ]

9 голосов
/ 28 марта 2012

То, что вы объявляете как IEnumerable<T>, не меняет тип время выполнения .Поэтому, когда вы передадите его своему представлению, представление будет знать во время компиляции , что оно IEnumerable<T>, но при наведении на него курсора во время отладки вы увидите фактический тип.(Непонятно, в какой момент вы зависали над Comment в представлении бритвы, но я сильно подозреваю это в середине сеанса отладки.)

Если вы хотите взятькопию данных, чтобы вы могли распоряжаться контекстом, просто позвоните ToList() и верните результат - вместо этого будет List<T>.

Обратите внимание, что эта разница времени компиляции / времени исполнения имеетничего общего с LINQ или MVC не имеет.Вы можете увидеть то же самое очень легко без каких-либо сложностей:

object value = "hello";

время компиляции тип value - object, что остановит ваш вызов Substring и т. Д.в теме.Но если вы наведите курсор мыши на value в сеансе отладки (или посмотрите на него в окне Watch или Local), вы увидите, что тип времени выполнения по-прежнему равен string.

EDIT: из вашегоedit:

Я звоню .ToList (), чтобы получить IEnumerable из IQueryable при выборе данных!

Я бы очень хотел увидеть этот код, потому что я нене думаю, что вы просто используете что-то вроде:

return query.ToList();

Если вы возвращаете результат вызова ToList(), то не будет быть EntitySet.

2 голосов
/ 28 марта 2012

Когда вы возвращаете ссылку на тип интерфейса, например 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() - это простой способ добиться этого.

...