Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need to cast a IQueryable<T> at runtime

Tags:

c#

linq-to-sql

I have done my research but I am still unable to find a solution to this problem. I have a program that is using lambda expressions with linq to sql. I would like to instantiate the main linq object as an dynamic object and cast it in the rest of the program to different types base off a value specified. For instance:

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

You cannot do what I am proposing above because the compiler complains about the Lambda expression. Can anyone help me out with this?

Update:

The error that I get when i change to dynamic is:

Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type

Update2:

There is one other problem with this, I have alot of logic that makes use of the data selected from the lamda expressions that happen above. Things like:

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

I would like to cast these values based on the the type selected from CurrentVal. So I'm thinking some type of reflection would be needed. Setting it to IQueryable is along the same lines as setting it to dynamic

So what I am thinking is something like, but I am not sure something like this is possible.

if (((IQueryable<CurrentVal>)val1).Where(c => c.ID == 3).Count() > 0)
{...}
like image 302
cjohns Avatar asked Mar 18 '11 18:03

cjohns


1 Answers

Instead of doing using dynamic for val initially, you can use IQueryable instead:

IQueryable val;

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

and than in your lambda you can cast appropriately.

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

Question: In your example you have the cast like this:

(IQueryable<datacontex.UniqueTable1>)val

Are you sure you just dont mean this

(IQueryable<UniqueTable1>)val

As it appears you are trying to cast via the collection on the data context?

On a side note, val1 will still be an IQueryable<T>, since you are just building the Where clause and not actually invoking the sql call, how are you going to invoke the ToList()?

Cast it back to an IQueryable<T>?

It seems like the use of dynamic here might not be the best approach as it seems to add unnecessary confusion, than to just separate out your data access layers for UniqueTable1 and UniqueTable2

like image 73
Mark Coleman Avatar answered Nov 05 '22 10:11

Mark Coleman