C# 实体框架通配符&;林克
是否可以构造包含通配符的有效Linq查询 我看到了这个问题的各种答案,建议使用:C# 实体框架通配符&;林克,c#,linq,entity-framework,odac,C#,Linq,Entity Framework,Odac,是否可以构造包含通配符的有效Linq查询 我看到了这个问题的各种答案,建议使用: .Where(entity => entity.Name.Contains("FooBar")) .Where(entity => entity.Name.EndsWith("Bar")) .Where(entity => entity.Name.StartsWith("Foo")) 或构造RawSql: var commandText = @"SELECT field FRO
.Where(entity => entity.Name.Contains("FooBar"))
.Where(entity => entity.Name.EndsWith("Bar"))
.Where(entity => entity.Name.StartsWith("Foo"))
或构造RawSql:
var commandText =
@"SELECT field
FROM table
WHERE field LIKE @search";
var query = new ObjectQuery<Profile>(commandText, context);
query.Parameters.Add(new ObjectParameter("search", wildcardSearch));
var命令文本=
@“选择字段
从桌子上
WHERE字段,如@search”;
var query=newobjectquery(commandText,context);
添加(新的ObjectParameter(“search”,wildcardSearch));
如果通配符不在字符串的开头或结尾,例如,searchTerm=“Foo%Bar”
,则第一种解决方案将不起作用
第二个解决方案是使用RawSql,它不适合我,而且感觉像是一个廉价的出路。但它确实有效
我还没有尝试的第三个选项是创建一些可以解析搜索词并构造有效Linq查询的东西,这是@Slauma在下面的链接2中尝试过的东西。但如果通配符不在搜索词的开头或结尾,这仍然不起作用
所以问题是:是否有可能构造一个包含通配符的有效Linq查询
编辑:
值得一提的是,在本例中,我使用的是Oracle数据访问组件(ODAC/ODP),但我认为在本例中没有多大区别
链接:
一,
二,
3.使用SqlFunctions.PatIndex,它将如下所示:
.Where(entity => SqlFunctions.PatIndex("Foo%Bar", entity.Name) > 0)
如果您使用EDMX文件作为实体模型的基础,那么您可以尝试创建一个在SQL中执行类似操作的文件。我不确定这是否适用于Oracle。然后,您应该能够执行以下操作:
.Where(entity => Like(entity.Name, "Foo%Bar"))
我为Oracle找到了一个很好的解决方案。这是另一个答案的一部分,也是我写的一部分
public static class LinqExtensions
{
public static IQueryable<T> WhereLike<T>(this IQueryable<T> source, String Name, String value)
{
Type model = typeof(T);
ParameterExpression param = Expression.Parameter(typeof(T), "m");
PropertyInfo key = model.GetProperty(Name);
MemberExpression lhs = Expression.MakeMemberAccess(param, key);
Expression<Func<T, String>> lambda = Expression.Lambda<Func<T, String>>(lhs, param);
return source.Where(BuildLikeExpression(lambda, value));
}
public static IQueryable<T> WhereLike<T>(this IQueryable<T> source, Expression<Func<T, String>> valueSelector, String value)
{
return source.Where(BuildLikeExpression(valueSelector, value));
}
public static Expression<Func<T, Boolean>> BuildLikeExpression<T>(Expression<Func<T, String>> valueSelector, String value)
{
if (valueSelector == null)
throw new ArgumentNullException("valueSelector");
value = value.Replace("*", "%"); // this allows us to use '%' or '*' for our wildcard
if (value.Trim('%').Contains("%"))
{
Expression myBody = null;
ParsedLike myParse = Parse(value);
Type stringType = typeof(String);
if(myParse.startwith!= null)
{
myBody = Expression.Call(valueSelector.Body, stringType.GetMethod("StartsWith", new Type[] { stringType }), Expression.Constant(myParse.startwith));
}
foreach (String contains in myParse.contains)
{
if (myBody == null)
{
myBody = Expression.Call(valueSelector.Body, stringType.GetMethod("Contains", new Type[] { stringType }), Expression.Constant(contains));
}
else
{
Expression myInner = Expression.Call(valueSelector.Body, stringType.GetMethod("Contains", new Type[] { stringType }), Expression.Constant(contains));
myBody = Expression.And(myBody, myInner);
}
}
if (myParse.endwith != null)
{
if (myBody == null)
{
myBody = Expression.Call(valueSelector.Body, stringType.GetMethod("EndsWith", new Type[] { stringType }), Expression.Constant(myParse.endwith));
}
else
{
Expression myInner = Expression.Call(valueSelector.Body, stringType.GetMethod("EndsWith", new Type[] { stringType }), Expression.Constant(myParse.endwith));
myBody = Expression.And(myBody, myInner);
}
}
return Expression.Lambda<Func<T, Boolean>>(myBody, valueSelector.Parameters.Single());
}
else
{
Expression myBody = Expression.Call(valueSelector.Body, GetLikeMethod(value), Expression.Constant(value.Trim('%')));
return Expression.Lambda<Func<T, Boolean>>(myBody, valueSelector.Parameters.Single());
}
}
private static MethodInfo GetLikeMethod(String value)
{
Type stringType = typeof(String);
if (value.EndsWith("%") && value.StartsWith("%"))
{
return stringType.GetMethod("Contains", new Type[] { stringType });
}
else if (value.EndsWith("%"))
{
return stringType.GetMethod("StartsWith", new Type[] { stringType });
}
else
{
return stringType.GetMethod("EndsWith", new Type[] { stringType });
}
}
private class ParsedLike
{
public String startwith { get; set; }
public String endwith { get; set; }
public String[] contains { get; set; }
}
private static ParsedLike Parse(String inValue)
{
ParsedLike myParse = new ParsedLike();
String work = inValue;
Int32 loc;
if (!work.StartsWith("%"))
{
work = work.TrimStart('%');
loc = work.IndexOf("%");
myParse.startwith = work.Substring(0, loc);
work = work.Substring(loc + 1);
}
if (!work.EndsWith("%"))
{
loc = work.LastIndexOf('%');
myParse.endwith = work.Substring(loc + 1);
if (loc == -1)
work = String.Empty;
else
work = work.Substring(0, loc);
}
myParse.contains = work.Split(new[] { '%' }, StringSplitOptions.RemoveEmptyEntries);
return myParse;
}
}
公共静态类LinqExtensions
{
公共静态IQueryable WhereLike(此IQueryable源、字符串名称、字符串值)
{
型号=型号(T);
ParameterExpression param=表达式参数(typeof(T),“m”);
PropertyInfo key=model.GetProperty(名称);
MemberExpression lhs=Expression.MakeMemberAccess(参数,键);
表达式lambda=表达式.lambda(lhs,param);
返回source.Where(BuildLikeExpression(lambda,value));
}
公共静态IQueryable WhereLike(此IQueryable源、表达式值选择器、字符串值)
{
返回source.Where(BuildLikeExpression(valueSelector,value));
}
公共静态表达式BuildLikeExpression(表达式值选择器,字符串值)
{
如果(valueSelector==null)
抛出新ArgumentNullException(“valueSelector”);
value=value.Replace(“*”,“%”;//这允许我们使用“%”或“*”作为通配符
如果(value.Trim(“%”)包含(“%”)
{
表达式myBody=null;
ParsedLike myParse=Parse(值);
类型stringType=typeof(字符串);
if(myParse.startwith!=null)
{
myBody=Expression.Call(valueSelector.Body,stringType.GetMethod(“StartsWith”,新类型[]{stringType}),Expression.Constant(myParse.startwith));
}
foreach(myParse.contains中包含的字符串)
{
如果(myBody==null)
{
myBody=Expression.Call(valueSelector.Body,stringType.GetMethod(“Contains”,新类型[]{stringType}),Expression.Constant(Contains));
}
其他的
{
表达式myInner=Expression.Call(valueSelector.Body,stringType.GetMethod(“Contains”,新类型[]{stringType}),表达式.Constant(Contains));
myBody=Expression.And(myBody,myInner);
}
}
if(myParse.endwith!=null)
{
如果(myBody==null)
{
myBody=Expression.Call(valueSelector.Body,stringType.GetMethod(“EndsWith”,新类型[]{stringType}),Expression.Constant(myParse.endwith));
}
其他的
{
表达式myInner=Expression.Call(valueSelector.Body,stringType.GetMethod(“EndsWith”,新类型[]{stringType}),表达式.Constant(myParse.endwith));
myBody=Expression.And(myBody,myInner);
}
}
返回表达式.Lambda(myBody,valueSelector.Parameters.Single());
}
其他的
{
表达式myBody=Expression.Call(valueSelector.Body,GetLikeMethod(value),Expression.Constant(value.Trim('%'));
返回表达式.Lambda(myBody,valueSelector.Parameters.Single());
}
}
私有静态MethodInfo GetLikeMethod(字符串值)
{
类型stringType=typeof(字符串);
if(value.EndsWith(“%”)和value.StartsWith(“%”)
{
返回stringType.GetMethod(“Contains”,新类型[]{stringType});
}
else if(value.EndsWith(“%”)
{
返回stringType.GetMethod(“StartWith”,新类型[]{stringType});
}
其他的
{
返回stringType.GetMethod(“EndsWith”,新类型[]{stringType});
}
}
类解析的私有类
{
公共字符串startwith{get;set;}
以{get;set;}结尾的公共字符串
公共字符串[]包含{get;set;}
}
私有静态类解析解析(字符串无效)
{
ParsedLike myParse=新的ParsedLike();
弦功=无效;
Int32 loc;
如果(!work.StartsWith(“%”)
{
work=work.TrimStart(“%”);
loc=工作指数(“%”);
myParse.startwith=work.Substring(0,loc);
功=功。子串(loc+1);
}
如果(!work.EndsWith(“%”)
{
loc=工时.最后索引OF('%');
myParse.endwith=work.Substring(loc+1);
如果(loc==-1)
work=String.Empty;
埃尔