Pri*_*ERO 5 c# where-clause .net-3.5 linq-to-sql
更新:现在正在工作
我终于完成了它.下面的答案中详述了一个工作示例(我将在2天内进行标记).
在过去的3天里,我一直在尝试使用来自此处和其他来源的问题的代码示例在DBML DataContext上构建一个dynamic-where子句...... 没有一个有效!
由于以下原因,我开始怀疑在Framework 3.5下是否可能使用它:
Invoke4.0中的等价版本(所以我在这里有一些希望).我真的很茫然,似乎在"抓住弦乐"......我需要一些关于如何处理这个问题的合理建议.
原始版本有一些成功,但只有在以下情况:
我只有成功的"成功"数据出现(所有6178行),但没有WHERE CLAUSE应用.这可以通过缺乏任何WHERE CLAUSE适用于SQL发现的证据来证明dataContext.GetCommand(query).CommandText.
其他版本#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;
}
Run Code Online (Sandbox Code Playgroud)
其他版本#2失败:
并生成此错误:"方法"布尔类似(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;
}
Run Code Online (Sandbox Code Playgroud)
这是正确的答案
这是为需要它的人提供的工作版本。这个问题是多种因素的结合。其中第一行设置为True:
var where = PredicateBuilder.True<vw_QuickFindResult>();
它应该是False...
var where = PredicateBuilder.False<vw_QuickFindResult>();
我不知道为什么......但还需要其他改变。
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 List<QuickFindResult> QueryDocuments(string searchText, string customerSiteId, List<int> filterIds)
{
var wildCards = new string[] { "*", "\"" };
var where = PredicateBuilder.False<vw_QuickFindResult>();
var searches = new List<String>(searchText.Split(' ')); // TODO: <-- If more complex searches are needed we'll have to use RegularExpressions
// SEARCH TEXT - WHERE Clause
searches.ForEach(productName =>
{
Boolean hasWildCards = (productName.IndexOfAny(new char[] { '"', '*' }) != -1);
if (hasWildCards)
{
Int32 length = productName.Length;
if (length > 1)
{
string like = productName.Replace("%", "")
.Replace("*", "");
string first = productName.Substring(0, 1);
string last = productName.Substring(length - 1);
// Contains
if (wildCards.Contains(first) && wildCards.Contains(last))
where = where.Or(p => p.DocumentName.Contains(like) ||
p.DocumentTitle.Contains(like));
// EndsWith
else if (wildCards.Contains(first))
where = where.Or(p => p.DocumentName.EndsWith(like) ||
p.DocumentTitle.EndsWith(like));
// StartsWith
else if (wildCards.Contains(last))
where = where.Or(p => p.DocumentName.StartsWith(like) ||
p.DocumentTitle.StartsWith(like));
// Contains (default)
else
where = where.Or(p => p.DocumentName.Contains(like) ||
p.DocumentTitle.Contains(like));
}
else // Can only perform a "contains"
where = where.Or(p => p.DocumentName.Contains(productName) ||
p.DocumentTitle.Contains(productName));
}
else // Can only perform a "contains"
where = where.Or(p => p.DocumentName.Contains(productName) ||
p.DocumentTitle.Contains(productName));
});
// FILTER IDS - WHERE Clause
var filters = GetAllFilters().Where(x => filterIds.Contains(x.Id)).ToList();
filters.ForEach(filter =>
{
if (!filter.IsSection)
where = where.And(x => x.FilterName == filter.Name);
});
var dataSource = DocumentCollectionService.ListQuickFind(where);
var collection = new List<QuickFindResult>();
// Other UNRELATED stuff happens here...
return collection;
}
public static List<vw_QuickFindResult> ListQuickFind(Expression<Func<vw_QuickFindResult, bool>> where)
{
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.Where(where).OrderBy(x => x.DocumentName).OrderBy(x => x.DocumentTitle);
results = query.ToList();
}
}
return results;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1915 次 |
| 最近记录: |