In the previous article LINQ to SQL Advanced Series (vi), we mentioned dynamic queries that use object. This article on the basis of the above, and then do more in-depth extension. At the same time fix some of the above wrong places.
1, the dynamic query of object continued
The first thing to do is to change the function of find to an extension method. An extension method can only be placed in a static class, and its first argument must take the This keyword. In the above, the author left a riddle. What do you do when you need an OR condition? This paper also gives an answer to this question. But for the dynamic like conditions, the author still has not found a better method. To increase the or condition, the declaration of the function is changed again. As follows:
public static iqueryable<tentity> find<tentity> (this iqueryable<tentity> source, tentity obj, bool Isand) where Tentity:class
In the above, we have also encountered a problem that system.nullable<int> such types do not support. The main reason for this place is that when we construct the right side of the expression tree, we do not give it parameters. Then this problem passes through Expression right = Expression.constant (P.getvalue (obj, null), P.propertytype); can be repaired. The whole function is modified as follows:
public static iqueryable<tentity> find<tentity> (this iqueryable<tentity> source, tentity obj, bool Isand) where Tentity:class
{
if (Source = null)
throw new ArgumentNullException ("Source can ' t be null!!");
Get all the property information
Propertyinfo[] Properties = obj. GetType (). GetProperties (BindingFlags.Public | BindingFlags.Instance);
Expression condition = null;
First, a ParameterExpression object is constructed, where C is the parameter in the lambda expression. (c=>)
This variable is moved out of the Foreach Loop
ParameterExpression param = Expression.parameter (typeof (Tentity), "C");
Traverse each property
foreach (PropertyInfo p in properties)
{
if (P!= null)
{
Type t = p.propertytype;
Supports only the value-type and string-type innuendo
if (T.isvaluetype | | t = = typeof (String))
{
If it's not NULL, it's a condition.
if (p.getvalue (obj, null)!= null)
{
SQL Server does not support comparison of TEXT, NTEXT, XML and IMAGE, etc
/**////only Support Bigint,bit,char,decimal,money,nchar,real,
Int,varchar,smallmoney,smallint,nvarchar,nvarchar (max), VarChar (max)
Attribute attr = Attribute.GetCustomAttribute (P, typeof (Columnattribute));
if (attr!= null)
{
String dbType = (attr as Columnattribute). DbType;
if (Dbtype.contains ("Text") | | dbtype.contains ("NText")
|| Dbtype.contains ("Xml") | | Dbtype.contains ("Image")
|| Dbtype.contains ("Binary") | | Dbtype.contains ("DateTime")
|| Dbtype.contains ("sql_variant") | | Dbtype.contains ("rowversion")
|| Dbtype.contains ("uniqueidentifier") | | Dbtype.contains ("VarBinary (MAX)")
{
Continue
}
}
To the right of the expression, the side of the value
Expression right = Expression.constant (P.getvalue (obj, null), P.propertytype);
The left side of the constructed expression, the property end.
Expression left = Expression.property (param, p.name);
Generate a filter expression. That is, C. CustomerID = "Tom"
Expression filter = Expression.equal (left, right);
if (condition = null)
{
condition = filter;
}
Else
{
if (Isand)
Condition = Expression.and (condition, filter);
Else
Condition = expression.or (condition, filter);
}
}
}
}
}
if (condition!= null)
{
Expression<func<tentity, bool>> pred = expression.lambda<func<tentity, bool>> (condition, param);
return source. Where (pred);
}
return source;
}