Ho la seguente tabella in SQL Server:Corporatura Espressione Albero convertibile a SQL valida in modo dinamico che può confrontare stringa con doppie
Tipi di prodotto
- Nome:
nvarchar(100)
- Valore:
nvarchar(200)
Questo è mappato tramite Entity Framework nella mia classe:
public class ProductAttribute
{
public string Name {get;set;}
public string Value {get;set;}
}
Alcune righe di ProductAttributes
avere la seguente forma:
{Name: "RAM", Value: "8 GB"}, {Name: "Cache", Value: "3000KB"}
ho bisogno di costruire dinamicamente un ExpressionTree che è convertibile a SQL che può fa il seguente:
Se il valore inizia con un numero seguito o meno da una stringa alfanumerica, estrarre il numero e confrontarlo con un dato valore
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; }
La cosa veramente brutta è che ho bisogno di costrutto questo albero espressione dinamicamente.
Finora ho gestito questa (questo considera il valore come decimale non come una stringa, quindi non prova nemmeno a fare tutta la roba regex):
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: Con l'aiuto fornito di seguito, questo funziona:
Expression<Func<ProductSpecification, bool>> expo = ps=> ps.Value.Substring(0, (SqlFunctions.PatIndex("%[^0-9]%", ps.Value + ".") ?? 0) - 1) == "1000";
Ma ho anche bisogno di un cast di raddoppiare e poi un confronto numerico che è:
Expression<Func<ProductSpecification, bool>> expo = ps=> double.Parse(ps.Value.Substring(0, (SqlFunctions.PatIndex("%[^0-9]%", ps.Value + ".") ?? 0) - 1)) > 1000;
Ovviamente questo non è convertibile in SQL: double.Parse()
.
Come è possibile creare il cast in modo che possa essere analizzato in SQL dalla mia espressione?
Quale sarebbe l'SQL che cosa vuoi generare? –
Francamente non lo so, ma qualcosa di equivalente a questo. –
Se i dati sono un lotto, è possibile che si verifichi un problema di prestazioni se questo tipo di query viene eseguito ancora e ancora, probabilmente INDICE non può essere utilizzato. Quindi un modo migliore è di avere una colonna numerica separata con valore numerico, è possibile aggiornare quella colonna al momento dell'inserimento/aggiornamento. – sallushan