I need to clean the value of a column in C# using linq.
Here is an example:
var p_name = "michaelscott";
var result = db.tablename.where(x => x.name
.Replace(" ",'')
.Replace("$","")
== p_name).FirstOrDefault();
This example only uses 2 items (spaces and dollar sign). if I wanted to add more things to clean, the linq query would be enormous, so I tried writing a method but it throws an error that this wasn't allowed. I then tried writing an extension class that did all the replaces with in it but it errors out with the same error as using a method.
Is there a way to do this without having to use a .Replace
for each character I want to remove?
Run an ad-hoc query within EF to easily acomplish what you're trying to do.
var cmd = "UPDATE dbo.TableName SET Name = REPLACE(REPLACE(t.Column, ' ', ''), '$', '')";
cmd += "FROM Table t";
cmd += "WHERE t.Name = value;";
context.Database.ExecuteSqlCommand(cmd);
Replaced with (I think) a better answer.
You can write a method to generate the proper Expression
to represent the cleaned-up value using an ExpressionVisitor
. The easiest way to use it is to write a new version of Where
so that type inference will work for you.
public static class IQueryableExt {
// body only for LINQ to Objects use
public static string RemoveAll(this string src, string removeChars) => removeChars.Aggregate(src, (ans,ch) => ans.Replace(ch.ToString(), ""));
private static Expression CleanUp(this Expression dbFn, string charsToRemove) {
var toCharE = Expression.Constant(String.Empty);
var replaceMI = typeof(string).GetMethod("Replace", new[] { typeof(string), typeof(string) });
var methodBody = dbFn;
foreach (var ch in charsToRemove)
methodBody = Expression.Call(methodBody, replaceMI, Expression.Constant(ch.ToString()), toCharE);
return methodBody;
}
/// <summary>
/// ExpressionVisitor to expand x.RemoveAll("x..z") to x.Replace("x","")...Replace("z","") in
/// an Expression.
/// </summary>
private class RemoveAllVisitor : ExpressionVisitor {
public override Expression Visit(Expression node) {
if (node?.NodeType == ExpressionType.Call) {
var callnode = (MethodCallExpression)node;
if (callnode.Method.Name == "RemoveAll" && callnode.Method.DeclaringType == typeof(IQueryableExt))
if (callnode.Arguments[1] is ConstantExpression ce && ce.Type == typeof(string))
return callnode.Arguments[0].CleanUp(ce.Value.ToString());
}
return base.Visit(node);
}
}
private static T ExpandRemoveAll<T>(this T orig) where T : Expression => (T)new RemoveAllVisitor().Visit(orig);
public static IQueryable<T> WhereRemoveAll<T>(this IQueryable<T> src, Expression<Func<T, bool>> predFn) => src.Where(predFn.ExpandRemoveAll());
}
With the extension code in place, using it is relatively easy:
var p_name = "michaelscott";
var result = db.tablename
.WhereRemoveAll(x => x.name.RemoveAll("$ ") == p_name)
.FirstOrDefault();
A more general approach might use something like LINQKit's approach to modify the query and automatically expand all embedded methods with some attribute - I added some code using this approach on CodeReview here .
you can use a Regex expression to catch all the characters you'd like to replace
var result = db.tablename(x =>
Regex.Replace(x, @"[^\w]", "")
== p_name).FirstOrDefault();
The above expression will remove all chars that are not a letter or number
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.