I have the following table in SQL Server:
ProductAttribute
- Name:
nvarchar(100)
- Value:
nvarchar(200)
This is mapped via Entity Framework into my class:
public class ProductAttribute
{
public string Name {get;set;}
public string Value {get;set;}
}
Some rows of ProductAttributes
have the following form:
{Name: "RAM", Value: "8 GB"}, {Name: "Cache", Value: "3000KB"}
I need to construct dynamically an ExpressionTree that is convertible to SQL that can does the following:
If the Value starts with a number followed or not by an alphanumeric string, extract the number and compare it with a given value
double value = ...; Expression<Func<ProductAttribute, bool>> expression = p => { Regex regex = new Regex(@"\d+"); Match match = regex.Match(value); if (match.Success && match.Index == 0) { matchExpression = value.Contains(_parserConfig.TokenSeparator) ? value.Substring(0, value.IndexOf(_parserConfig.TokenSeparator)) : value; string comparand = match.Value; if(double.Parse(comparand)>value) return true; } return false; }
The really nasty thing is that I need to construct this expression tree dynamically.
So far I've managed this (this considers the value as a decimal not as a string, so it doesn't even try to do the whole regex stuff):
private Expression GenerateAnyNumericPredicate(
Type type,
string valueProperty,
string keyValue,
double value) {
ParameterExpression param = Expression.Parameter(type, "s");
MemberExpression source = Expression.Property(param, valueProperty);
ConstantExpression targetValue = GetConstantExpression(value, value.GetType());
BinaryExpression comparisonExpression = Expression.GreaterThan(source, targetValue);
return Expression.Lambda(comparisonExpression, param);
}
EDIT: With the help provided below, this works:
Expression<Func<ProductSpecification, bool>> expo = ps=> ps.Value.Substring(0, (SqlFunctions.PatIndex("%[^0-9]%", ps.Value + ".") ?? 0) - 1) == "1000";
But I also need a cast to double and then a numeric comparison that is:
Expression<Func<ProductSpecification, bool>> expo = ps=> double.Parse(ps.Value.Substring(0, (SqlFunctions.PatIndex("%[^0-9]%", ps.Value + ".") ?? 0) - 1)) > 1000;
Obviously this is not convertible to SQL: double.Parse()
.
How could I construct the cast so it can be parsed into SQL from my Expression?