I'm using the Dynamic Linq
with Linq to Entities
So, I tested the normal List<Person>
with this code and everything's work:
List<Person> per = new List<Person>();
per.Add(new Person { IdNo = "1", LastName = "test", MiddleName = "go", FirstName = "let" });
per.Add(new Person { IdNo = "2", LastName = "hope", MiddleName = "is", FirstName = "way" });
per.Add(new Person { IdNo = "3", LastName = "must", MiddleName = "be", FirstName = "human" });
per.Add(new Person { IdNo = "4", LastName = "thing", MiddleName = "anywhere", FirstName = "can" });
per.Add(new Person { IdNo = "5", LastName = "bird", MiddleName = "fly", FirstName = "away" });
List<object> paramObjects = new List<object>();
List<string> fields = new List<string>();
fields.Add("IdNo == @0");
paramObjects.Add("1");
fields.Add("or (LastName + \", \" + MiddleName + \" \" + FirstName).Contains(@1)");
paramObjects.Add("m");
var where = string.Join(" ", fields.ToArray());
var toParam = paramObjects.ToArray();
var query = per.AsQueryable().Where(where, toParam).ToList();
and when I'm in Linq To Entities
approach.
using(var con = new DbContext())
{
var query = con.Person.Where(where, toParam).ToList();
}
I got this error:
LINQ to Entities does not recognize the method 'System.String Concat(System.Object, System.Object)' method, and this method cannot be translated into a store expression.
My question is:
How to Concat
the string using the Linq To Entities
base in my example using the Dynamic Linq? Anyone can help me?
Option 1:
Change the line...
fields.Add("or (LastName + \", \" + MiddleName + \" \" + FirstName).Contains(@1)");
...to
fields.Add("or string.Concat(LastName, \", \", MiddleName, \" \", FirstName).Contains(@1)");
Option 2:
Open the Dynamic.cs
file of the Dynamic LINQ library, search for "GenerateStringConcat"
in that file. You should find this method:
Expression GenerateStringConcat(Expression left, Expression right) {
return Expression.Call(
null,
typeof(string).GetMethod("Concat",
new[] { typeof(object), typeof(object) }),
new[] { left, right });
}
Change the object
parameter types to string
, that is:
Expression GenerateStringConcat(Expression left, Expression right) {
return Expression.Call(
null,
typeof(string).GetMethod("Concat",
new[] { typeof(string), typeof(string) }),
new[] { left, right });
}
Keep in mind that Dynamic LINQ is not a special "LINQ-to-Entities library", but a general library for IQueryable
. There might be Queryable providers that support string.Concat(object, object)
with the general object
parameter, but LINQ-to-Entities does not. It only supports the string
parameter versions of string.Concat
. Looking through the Dynamic LINQ file when GenerateStringConcat
is actually called (only once) I believe the change above is safe as long as you only want to use the library with LINQ-to-Entities/Entity Framework.
Edit
Option 1 does not work because Concat
gets more than four string parameters in the example. It only works up to four parameters because string.Concat
has an overload with four explicit string
parameters. It doesn't seem to be possible to use the overload with the array parameter params string[]
in Dynamic LINQ.
I had the same problem but with NHibernate, my solution was to modify GenerateStringConcat Method
I change this:
static Expression GenerateStringConcat(Expression left, Expression right)
{
return Expression.Call(
null,
typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }),
new[] { left, right });
}
For this:
static Expression GenerateStringConcat(Expression left, Expression right)
{
return Expression.Add(
left,
right,
typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) })
);
}
He has worked quite well :)