Applying Linq Expression to IQueryable OrderBy - linq

Linq2Rest generates SortDescriptions with KeySelectors of type Expressions<Func<T, U>>
Assuming I have an IQueryable<MyObject>. A KeySelector can be applied to IQueryable.OrderBy as follows:
var keySelector = SortDescription.KeySelector;
if(keySelector.Type.Equals(typeof(Func<MyObject, Int64>)
{
queryable = querable.OrderBy<MyObject, Int64>(
keySelector as Expression<<Func<MyObject, Int64>>);
}
Is there a way to dynamically match the Type of the KeySelector to the queryable.OrderBy method so that I do not have to compare and invoke the method by Type? In an ideal world I would be able to write the following code.
queryable = queryable.OrderBy(keySelector);
But that results in
The type arguments for method Queryable.OrderBy<TSource, TKey>(IQueryable<TSource>, Expression<Func<TSource, TKey>>) cannot be inferred from the usage. Try specifying the type arguments explicitly.

Related

How to pass an argument to a function when using ParameterExpression together with org.springframework.data.jpa.domain.Specification?

I am using org.springframework.data.jpa.domain.Specification together with JpaSpecificationExecutor to easily create queries with conditions in Java but now I need to call a MySQL DB function that returns an integer value.
The problem is that it is unclear how to pass an argument for this function as I am not using TypedQuery:
// cb here is CriteriaBuilder
ParameterExpression param = cb.parameter(String.class);
Predicate predicate = cb.greaterThan(cb.function("A_FUNCTION",
Integer.class, param), 0);
Specification spec = cb.and(predicate);
// query is executed like this
return (int) repositoryThatExtendsJpaSpecificationExecutor.count(test);
And the example from here is not helping.
I think what you really need is a literal which you can create using CriteriaBuilder.literal. A full example would look like
// cb here is CriteriaBuilder
Expression param = cb.literal("Stephen Hawking");
Predicate predicate = cb.greaterThan(cb.function("A_FUNCTION",
Integer.class, param), 0);
Specification spec = cb.and(predicate);
If the value doesn't come from your application you can use (m)any of the functions returning an Expression.

Is string functions used in linq queries breaks down into query expressions?

I have the scenario, where i am using string equals method for comparison with the data in db and it is breaking down into query expressions, so how its working? Do Linq supports all c# methods in the queries or only string class methods.
var us = "uttams";
IQueryable<UserData> use = (from user in entity.Users
where user.UserName.equals(us)
select new UserData{ UserName = user.UserName }).AsQueryable<UserData>();
var name = use.FirstOrDefault().UserName;
There is a set of methods that are supported, and all the others are not supported (you should think about it as a whitelist).
CLR Method to Canonical Function Mapping
Boolean Equals(String a, String b) method is translated into = operator in SQL query.

Linq query returns null. Can't figure out why

My result returns null.
IEnumerable<DataRow> result = ( from r in db.vedhaeftedeFilers.AsEnumerable() where r.beskedId == id select new { r.filnavn, r.filtype, r.data })as IEnumerable<DataRow>;
there are data in the database, and the id are correct. I am guessing that it has
something to do with my use of IEnumerable, but cant figure out what the problem is.
The as operator will return null if the object you are passing is not actually an IEnumerable<DataRow>, which it obviously is not because you are projecting into an anonymous type with select new { ... }.
As an aside, the AsEnumerable() call will ruin your performance by making your database table behave like a dumb array.
What exactly are you trying to do here?
select new { r.filnavn, r.filtype, r.data }
That creates an anonymous type with read only properties filnavn, filtype and data. Thus the type of the LINQ comprehension expression (from ... select) is IEnumerable<anonymous>.
This type does not implement IEnumerable<DataRow>, so as Jon notes, it will return null.
When you do this:
select new { r.filnavn, r.filtype, r.data }
...you are returning a collection of an anonymous type. This is a problem because you're trying to cast this collection to IEnumerable<DataRow>. Since you're using as to cast, it's "dying silently" and returning null since casting with the as keyword doesn't throw an InvalidCastException if the cast fails (as opposed to casting with parethesis like MyClass x = (MyClass)MyObj).
Try this instead:
var result = ( from r in db.vedhaeftedeFilers.AsEnumerable() where r.beskedId == id select new { r.filnavn, r.filtype, r.data });
Notice I used var and didn't attempt to cast the result to a type.

Var vs IEnumerable when it comes to Entity Framework

If I were to use IEnumerable instead of var in the code example below, will the SQL be generated only during the execution of the foreach statement? Or will it execute as an when the Linq statements are evaluated?
var query = db.Customers.Where (c => c.Age > 18);
query = query.Where (c => c.State == "CO");
var result = query.Select (c => c.Name);
foreach (string name in result) // Only now is the query executed!
Console.WriteLine (name);
Another example:
IEnumerable<Order> query = db.Orders.Where(o => o.Amount > 1000);
int orderCount = query.Count();
Would it be better to use var (or IQueryable) as it would be executed a select count(*)... when .Count() is executed or would it be exactly same with the IEnumerable code shown above?
It would make no difference. var is just syntactic sugar. If you hover over var, you will see what type C# thinks your query is.
From http://msdn.microsoft.com/en-us/library/bb383973.aspx
Beginning in Visual C# 3.0, variables that are declared at method scope can have an implicit type var. An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type. The following two declarations of i are functionally equivalent:
var i = 10; // implicitly typed
int i = 10; //explicitly typed
If you want to perform actions on your query that SQL wouldn't know what to do with, such as a method defined in your class, then you could use AsEnumerable().
For example:
var query = db.Customers
.Where(c => c.Age > 18)
.AsEnumerable()
.Select(c => GetCustomerViewModel());
//put definition of GetCustomerViewModel() somewhere in the same class
Update
As Omar mentioned, if you want your query to be executed immediately (rather than deferred), use ToList(). This will immediately enumerate the IQueryable/IEnumerable and fill the list with the actual data from the database.
In general, the SQL is generated when GetEnumerator is called on the IQueryable.
In your example, there is a subtle difference that you may want to consider. Let's take your original example:
var query = db.Customers.Where (c => c.Age > 18);
query = query.Where (c => c.State == "CO");
var result = query.Select (c => c.Name);
In this case if you change your first query to IEnumerable query = ..., then the second line would use the IEnumerable version of the Where extension (LINQ to Objects) rather than the IQueryable one (LINQ to SQL/EF). As a result, when we start iterating, the first where clause is passed to the database, but the second where clause is performed on the client side (because it has already been converted to an IEnumerable).
Another subtle item you want to be aware of is the following type of code:
var query = db.OrderBy(c => c.State);
query = query.Customers.Where(c => c.Age > 18); // Fails: Widening
In this case, since your original query returns IOrderedQueryable rather than IQueryable. If you try to then assign query to the result of the .Where operation, you're trying to widen the scope of the return type and the compiler will refuse to perform that widening. As a result, you have to explicitly specify the baseline type rather than using var:
IQueryable<Customer> query = db.OrderBy(c => c.State); // Is narrowing rather than widening.
query = query.Customers.Where(c => c.Age > 18);
Linq queries return IQueryable<> or IEnumerable<>, the execution of both is deferred.
As DanM stated, whether or not you use var or IEnumerable<> it all depends on the return value of the method you're calling: if it's an IEnumerable<> or IQuerable<> it'll be deferred, if you use .ToList(), it'll be executed right away.
When to use var comes down to personal choice/style. I generally use var when the return value is understood from the line of code and variable name or if I'm instantiating a generic with a long declartion, e.g. Dictionary<string, Func<Order, object>>.
From your code, it's clear that a collection of Customers/Orders is returned, so I would use the var keyword. Again, this is a matter of personal preference.

LINQ on System.Object (type known only at runtime using reflection)

I have a simlar requirement where in i have 3 main entities in ADO.NET entity model... I am building a framework wherein basedon incoming XML root element i have to create an instance of specific entity using reflection and set its properties..
But when it comes to child entities.. I am not able to use LINQ queries on it as the type is not known at design time. PropertyInfo.GetValue gives me an object on which i can not run LINQ queries (even when i typecast it to IQueryable or IEnumerable). I am not even able to typecast it at design time as that would be kind of hardcoding and will fail my generic framework purpose.
I tried to use dynamic keyword.. but on that too i can not write LINQ queries.. it gives a message that LINQ queries are not supported on dynamic dispatch model.!!!
Can someone help..
Regards Badal
Like #Yuriy Faktorovich recommended, dynamic LINQ may be your best shot.
Another option you have is to dynamically build expression trees and execute your expression via reflection. Keep in mind that this is not easy and may take a little time to wrap your head around the expression API, but for simple expression it's not too bad.
Example: Say you want to replicate this expression:
p => p.FirstName == firstName
You can build the expression tree as follows:
var myType = Type.GetType("Person"); // <-- Find your type based on XML
var firstName = "John";
var param = Expression.Parameter(myType, "p");
var firstNameProperty = Expression.Property(param, "FirstName");
var constantExpression = Expression.Constant(firstName);
var equalsExpression = Expression.Equal(firstNameProperty, constantExpression);
var lambda = Expression.Lambda(equalsExpression, param);
The lambda will have a runtime type of Expression<Func<Person,bool>> which you can then pass to any IQueryable implementation.
UPDATE
Then to dynamcially call some method on your IQueryable you can do something similar to the following:
var queryableType = typeof(Queryable);
var whereMethod = queryableType.GetMethod("Where", BindingFlags.Public | BindingFlags.Static);
var parameters = new object[] { query, lambda }; // query is your IQueryable object
var list = whereMethod.Invoke(null, parameters);

Resources