UPDATE: It Is Now Working
I was able to finally get it completed. A working-example is detailed in an answer below (which I will be able to mark-off in 2 days).
Everything Below Here Was Part of the Original Question
For the last 3 days, I have been trying to build a dynamic-where-clause on a DBML DataContext using code samples from questions posted here and from other sources as well...none have worked!
出于以下原因,我开始问,根据《框架》3.5,这是否甚至是《最低业务安全标准》:
- Predicate Builder notes Framework 4.0 on their site.
- Some answers here talk about an equivolent
Invoke
versions in 4.0 (so I have some hope here). - ...I could go on but you get the idea.
我确实遭受损失,似乎“在扼杀时感到悲伤”。 我需要就如何解决这一问题提出一些合理的建议。
Original Version Had SOME Success But Only When:
The ONLY time I had a inkling of success the data came-up (all 6178 rows of it) but no WHERE CLAUSE
was applied. This was evidenced by the lack of any WHERE CLAUSE
applied into the SQL
found in the dataContext.GetCommand(query).CommandText
.
Other Version #1 Fails:
And generates this error: "Method System.Object DynamicInvoke(System.Object[]) has no supported translation to 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;
}
Other Version #2 Fails:
And generates this error: "Method Boolean Like(System.String, System.String) cannot be used on the client; it is only for translation to 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;
}