更新:它正在运行
我终于能够完成它。下面的答案中详细介绍了一个工作示例(我将能够在 2 天内划定)。
下面的所有内容都是原始问题的一部分
在过去的 3 天里,我一直在尝试在 DBML DataContext 上构建一个动态 where 子句。使用来自 questions posted here 的代码示例来自other sources还有...没有一个起作用!
由于以下原因,我开始怀疑在 Framework 3.5 下使用它是否可行:
- Predicate Builder在他们的网站上注意到 Framework 4.0。
- 一些 answers here讨论 4.0 中的等效
Invoke
版本(所以我在这里有一些希望)。 - ...我可以继续,但你明白了。
我真的很茫然,似乎在“捕获字符串”......我需要一些关于如何处理这个问题的合理建议。
原版有SOME Success但仅当:
唯一一次我有一个成功的“暗示”数据出现(所有 6178 行)但没有应用 WHERE CLAUSE
。 缺少 WHERE CLAUSE
应用于 dataContext.GetCommand(query).CommandText< 中的
.SQL
证明了这一点
其他版本 #1 失败:
并生成此错误:“方法‘System.Object DynamicInvoke(System.Object[])’没有支持的 SQL 转换。”
// VERSION 1:
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
public static Expression<Func<T, bool>> StringLike<T>(Expression<Func<T, string>> selector, string pattern)
{
var predicate = PredicateBuilder.True<T>();
var parts = pattern.Split('%');
if (parts.Length == 1) // not '%' sign
{
predicate = predicate.And(s => selector.Compile()(s) == pattern);
}
else
{
for (int i = 0; i < parts.Length; i++)
{
string p = parts[i];
if (p.Length > 0)
{
if (i == 0)
{
predicate = predicate.And(s => selector.Compile()(s).StartsWith(p));
}
else if (i == parts.Length - 1)
{
predicate = predicate.And(s => selector.Compile()(s).EndsWith(p));
}
else
{
predicate = predicate.And(s => selector.Compile()(s).Contains(p));
}
}
}
}
return predicate;
}
}
// VERSION 1:
public List<QuickFindResult> QueryDocuments(string searchText, string customerSiteId, List<int> filterIds)
{
var where = PredicateBuilder.True<vw_QuickFindResult>();
var searches = new List<String>(searchText.Split(' '));
searches.ForEach(productName =>
{
string like = productName.Replace('"', '%')
.Replace('*', '%');
where = PredicateBuilder.StringLike<vw_QuickFindResult>(x => x.DocumentName, like);
});
var results = DocumentCollectionService.ListQuickFind(where, null);
// Do other stuff here...
return results;
}
// VERSION 1:
public static List<vw_QuickFindResult> ListQuickFind(Expression<Func<vw_QuickFindResult, bool>> where, Expression<Func<vw_QuickFindResult, bool>> orderBy)
{
var connectionString = GetConnectionString(ES_DOCUMENTS_CONNECTION_NAME);
List<vw_QuickFindResult> results = null;
using (HostingEnvironment.Impersonate())
{
using (var dataContext = new ES_DocumentsDataContext(connectionString))
{
IQueryable<vw_QuickFindResult> query = dataContext.vw_QuickFindResults;
query = query.Where(where);
results = query.ToList();
}
}
return results;
}
其他版本 #2 失败:
并生成此错误:“无法在客户端使用方法‘Boolean Like(System.String, System.String)’;它仅用于转换为 SQL。”
// VERSION 2:
public List<QuickFindResult> QueryDocuments(string searchText, string customerSiteId, List<int> filterIds)
{
Func<vw_QuickFindResult, bool> where = null;
Func<string, Func<vw_QuickFindResult, bool>> buildKeywordPredicate = like => x => SqlMethods.Like(x.DocumentName, like);
Func<Func<vw_QuickFindResult, bool>, Func<vw_QuickFindResult, bool>, Func<vw_QuickFindResult, bool>> buildOrPredicate = (pred1, pred2) => x => pred1(x) || pred2(x);
// Build LIKE Clause for the WHERE
var searches = new List<String>(searchText.Split(' '));
searches.ForEach(productName =>
{
string like = productName.Replace('"', '%')
.Replace('*', '%');
where = (where == null) ? buildKeywordPredicate(like) : buildOrPredicate(where, buildKeywordPredicate(like));
});
var results = DocumentCollectionService.ListQuickFind(where, null);
// Do other stuff here...
return results;
}
// VERSION 2:
public static List<vw_QuickFindResult> ListQuickFind(Expression<Func<vw_QuickFindResult, bool>> where, Expression<Func<vw_QuickFindResult, bool>> orderBy)
{
var connectionString = GetConnectionString(ES_DOCUMENTS_CONNECTION_NAME);
List<vw_QuickFindResult> results = null;
using (HostingEnvironment.Impersonate())
{
using (var dataContext = new ES_DocumentsDataContext(connectionString))
{
var query = dataContext.vw_QuickFindResults.AsEnumerable();
query = query.Where(where);
results = query.ToList();
}
}
return results;
}
最佳答案
您是否尝试过仅使用表达式类自己构建查询? 那里应该没有特别的问题。其实还是比较容易学的。 您可以编写一个示例查询,然后在调试中查看它是如何组成的:
Expression<Func<string, bool>> exp = (s) => s.Contains("your query");
然后简单看一下watch中的exp变量,就可以看出结构了。 这个特定的例子应该像这样组成:
Expression constant = Expression.Constant("your query");
Expression p = Expression.Param(typeof(string);
Expression contains = Expression.Call(p, "Contains", constant);
Expression<Func<string, bool>> lambda = Expression.Lamba(contains, p);
// Now you can send this to your ORM
关于c# - Linq-To-Sql Dynamic-Where-Clauses 在 Framework 3.5 中甚至可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8153260/