Приводит ли Cast <T>к вычислению IQueryable в Linq-to-SQL?Каковы ограничения на его использование? - PullRequest
3 голосов
/ 28 февраля 2011

Приводит ли Cast к вычислению IQueryable в Linq-to-SQL?

Каковы ограничения на его использование?

Кажется, будто я создал явное преобразование для записи в объект домена, например:

  IQueryable<TSqlRecord> q;
  var cast = q.Cast<TDomainObject>();

Тогда я должен получить ошибку, потому что Linq-to-Sql и, очевидно, не может обработать конструктор объекта домена.

Но можно ли привести IQueryable<TSqlRecord> к его интерфейсу IHasIntId, не заставляя запрос оценивать?

Ответы [ 2 ]

4 голосов
/ 28 февраля 2011

Приведение откладывается и не вызывает немедленного выполнения. Это потому, что он (сам) не перечисляет источник. Запрос выполняется только тогда, когда что-то перечислено.

Upcasting не проблема. Запрос будет работать нормально.

Напомним - запрос работает со строками базы данных, а не с экземплярами. Экземпляры создаются только тогда, когда строки поступают локально. Все, что делает этот вызов cast, это изменяет ссылочный тип, используемый в результате - он не меняет тип экземпляра new'd up.

class SpecificObject : DomainObject

MyDataContext myDC = new MyDataContext();
IQueryable<DomainObject> query = myDC.SpecificObjects.Cast<DomainObject>();

Console.WriteLine(myDC.GetCommand(query).CommandText);

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


Даункастинг на самом деле мало что делает. LinqToSql предполагает, что каждая строка имеет тип T из Table<T>. Не какой-то ТЧилд. Это сгенерирует запрос, выбирающий нуль для каждой строки в таблице.

class SpecificObject : DomainObject

MyDataContext myDC = new MyDataContext();
IQueryable<SpecificObject> query = myDC.DomainObjects.Cast<SpecificObject>();

Console.WriteLine(myDC.GetCommand(query).CommandText);

Неявное преобразование ... с этим нужно быть очень осторожным. Даже Enumerable.Cast<T> LinqToObject не учитывает неявные операции преобразования (см. здесь и здесь ). Конечно, это не имеет ничего общего с LinqToSql - но принцип имеет значение - приведение .net не то же самое, что неявное преобразование c # и все, что связано с SQL. Вы должны иметь в виду среду исполнения кода, который вы пишете.

2 голосов
/ 28 февраля 2011

Нет, вы не можете привести IQueryable<TSqlRecord> к IHasIntId, потому что IQueryable<TSqlRecord> представляет несколько объектов типа TSqlRecord, тогда как IHasIntId представляет только один объект. По крайней мере, так я понимаю твой образец.
Я думаю, ваш вопрос должен был быть задан так:

Можно ли разыграть IQueryable<TSqlRecord> до IQueryable<IHasIntId>.

Ответ на этот вопрос: Нет, это невозможно
MSDN гласит следующее:

Метод Cast (IQueryable) генерирует выражение MethodCallExpression, которое представляет сам вызов Cast (IQueryable) как созданный универсальный метод. Затем он передает метод MethodCallExpression в метод CreateQuery (Expression) объекта IQueryProvider, представленного свойством Provider исходного параметра.

Поведение запроса, возникающее в результате выполнения дерева выражений, представляющего вызов Cast (IQueryable), зависит от реализации типа параметра источника. Ожидаемое поведение - преобразование значений в источнике в тип TResult.

Это означает, что вызов Cast в действительности не выполняется, но интерпретируется поставщиком запросов и, например, переводится в SQL.

...