Let's have the following:
public interface IOne {
UInt64 Id { get; }
Int16 Size { get; }
}
public interface ITwo {
UInt64 OneId { get; }
Int16 Color { get; }
}
As explained here the way to reuse a linq expression is to write something like this:
public static Expression<Func<IOne, bool>> MyWhereExpression( int value ){
return (o) => (o.Size > value);
}
int v = 5;
IQueryable<IOne> records = from one in s.Query<IOne>()
.Where(MyWhereExpression(v))
select one;
When I want to do the same with two tables I encounter a problem.
The expression:
public static Expression<Func<IOne, ITwo, bool>> MyWhereExpression2(int color ) {
return (one,two) => (one.Id == two.OneId) && (two.Color > color );
}
Linq 1:
int color = 100;
IQueryable<IOne> records = from one in s.Query<IOne>()
from two in s.Query<ITwo>()
.Where(MyWhereExpression2(color))
select one;
This doesn't work as .Where sticks to only the 2nd from.
Linq 2:
int color = 100;
IQueryable<IOne> records = (from one in s.Query<IOne>()
from two in s.Query<ITwo>()
select new { one, two })
.Where(MyWhereExpression2(color));
This results in
Argument 2: cannot convert from 'Expression<System.Func<IOne,ITwo,bool>>' to 'System.Func<AnonymousType#1,int,bool>'
I understand the error message about the AnonymousType, but I cannot figure out how to write the query.
The reason why I want to use an expression rather than just write
where (one.Id == two.OneId) && (two.Color > color )
directly in the linq query is because I want to reuse this expression in multiple linq queries.
LINQ applies the principles of object-oriented programming to relational data. It provides a unified programming model for querying data from different types of data sources, and extends data capabilities directly into the C# and Visual Basic languages. For more information, see Language-Integrated Query (LINQ).
The Let keyword allows you to create a range variable and initialized with the result of the query expression and then you are allowed to use that variable with the upcoming clause in the same query.
LINQ provides you three different ways to write a LINQ query in C# or VB.
There may be a more elegant solution that escapes me at the moment, but you could just use Tuple<IOne, ITwo>
instead of the anonymous type:
static Expression<Func<Tuple<IOne, ITwo>, bool>> MyWhereExpression2(int color) {
return t => (t.Item1.Id == t.Item2.OneId) && (t.Item2.Color > color);
}
int color = 100;
IQueryable<IOne> records = (from one in s.Query<IOne>()
from two in s.Query<ITwo>()
select Tuple.Create(one, two))
.Where(MyWhereExpression2(color))
.Select(t => t.Item1);
UPDATE: I probably answered too quickly above as that won't work with Linq to SQL since the call to Tuple.Create cannot be translated to SQL. To work with Linq to SQL, the only solution I see at the moment is to create a named type:
class Pair
{
public IOne One { get; set; }
public ITwo Two { get; set; }
}
static Expression<Func<Pair, bool>> MyWhereExpression2(int color) {
return p => (p.One.Id == p.Two.OneId) && (p.Two.Color > color);
}
int color = 100;
IQueryable<IOne> records = (from one in s.Query<IOne>()
from two in s.Query<ITwo>()
select new Pair { One = one, Two = two })
.Where(MyWhereExpression2(color))
.Select(p => p.One);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With