Нужно разыграть IQueryable <T>во время выполнения - PullRequest
4 голосов
/ 18 марта 2011

Я провел исследование, но все еще не могу найти решение этой проблемы. У меня есть программа, которая использует лямбда-выражения с linq to sql. Я хотел бы создать экземпляр основного объекта linq как динамический объект и привести его в остальной части программы к различным типам на основе указанного значения. Например:

int Value1 = 'Ob1';
int Value2 = 'OB2';

int Currentval = Value1;

dynamic val;

if (Currentval == Value1;
        val = (from c in datacontext.UniqueTable1
               select c);
else
        val = (from c in datacontext.UniqueTable2
               select c);


dynamic val1;

if (Currentval == Value1)
{
  val1 = ((IQueryable<datacontex.UniqueTable1>)val).Where(c => c.ID == 2);
}
else if (Currentval == Value1)
{
  val1 = ((IQueryable<datacontex.UniqueTable2>val).Where(c => c.ID == 3);
}

Вы не можете делать то, что я предлагаю выше, потому что компилятор жалуется на лямбда-выражение. Кто-нибудь может мне помочь с этим?

Обновление:

Ошибка, которую я получаю при переходе на динамический:

Невозможно использовать лямбда-выражение в качестве аргумента для динамически отправляемой операции без предварительного приведения его к типу дерева делегата или выражения

Update2:

Есть еще одна проблема с этим, у меня есть много логики, которая использует данные, выбранные из выражений lamda, которые происходят выше. Вещи как:

if (val1.Where(c => c.ID == 3).Count() > 0)
{...}

Я хотел бы привести эти значения в зависимости от типа, выбранного из CurrentVal . Поэтому я думаю, что понадобится какое-то отражение. Установка IQueryable аналогична установке dynamic

Так что я думаю, что-то вроде, но я не уверен, что что-то подобное возможно.

if (((IQueryable<CurrentVal>)val1).Where(c => c.ID == 3).Count() > 0)
{...}

Ответы [ 2 ]

4 голосов
/ 18 марта 2011

Вместо того, чтобы изначально использовать динамический для val, вы можете использовать IQueryable вместо:

IQueryable val;

if (Currentval == Value1)
{
    val = (from c in datacontext.UniqueTable1
            select c);
}
else
{
    val = (from c in datacontext.UniqueTable2
            select c);
}

и, чем в вашей лямбде, вы можете разыграть соответственно.

if (Currentval == Value1)
{
    val1 = ((IQueryable<UniqueTable1>)val).Where(c => c.Id == 2);
}
else if (Currentval == Value1)
{
    val1 = ((IQueryable<UniqueTable2>)val).Where(c => c.Id == 3);
}

Вопрос:В вашем примере у вас есть приведение типа:

(IQueryable<datacontex.UniqueTable1>)val

Вы уверены, что просто не имеете в виду это

(IQueryable<UniqueTable1>)val

Как кажется, вы пытаетесь выполнить приведение через коллекцию данныхcontext?

В примечании val1 по-прежнему будет IQueryable<T>, так как вы просто строите предложение Where и фактически не вызываете вызов sql, как вы собираетесьчтобы вызвать ToList()?

Привести его обратно к IQueryable<T>?

Похоже, что использование динамического здесь не может быть лучшим подходом, так как кажется, добавляет ненужную путаницу, чем просто разделить ваши слои доступа к данным для UniqueTable1 и UniqueTable2

0 голосов
/ 18 октября 2018

Это сработало для меня:

val = (from c in datacontext.UniqueTable1 select c)*.AsQueryable()*;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...