如何使用传递的字符串参数从控制器编写 MVC Entity Framework select 查询?
How do I write an MVC Entity Framework select query from the controller using passed string arguments?
我在 MVC 中创建了一个搜索工具。用户将 searchTerm 字符串键入搜索框和 selects 选项以从 2 个下拉 select 列表中进行搜索。在第一个列表中,用户 selects "Fuzzy" 或 "Literal" 用于搜索类型,在第二个列表中,用户可以 select 搜索特定字段,specField。单击搜索按钮后,3 个字符串值将传递给控制器。
我正在尝试编写一个 "if" 语句,该语句根据传入控制器的这 3 个字符串值查询 Entity Framework 数据库模型。如何编写使用这些值的查询?
这就是我所拥有的。我知道查询没有写正确:
Public PartialViewResult _Search(string searchTerm, string specField, string searchType)
{
//This works to populate the table with the entire DB
_db = new IntegrationDBEntities();
var request = (from r in _db.Requests
select r).ToList();
//These two are not correct and I need help writing these
if (searchType == "Fuzzy" && searchTerm != "" && specField != "None")
{
request = (from r in _db.Requests
where r.(specField).Contains(searchTerm)
select r).ToList();
}
if (searchType == "Literal" && searchTerm != "" && specField == "None")
{
request = (from r in _db.Requests
where r.Equals(searchTerm)
select r).ToList();
}
ViewData.Model = request;
Return partialView();
}
希望这没有错误:
ParameterExpression pe = Expression.Parameter(typeof(Request), "Request");
Expression property = Expression.Property(pe, specField);
Expression predicate = null;
Expression srch = Expression.Constant(searchTerm, typeof(string));
if(searchType == "Fuzzy")
{
MethodInfo contains = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
predicate = Expression.Call(property, contains, srch);
}
else
{
predicate = Expression.Equal(property, srch);
}
MethodCallExpression where = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { _db.Requests.ElementType },
_db.Requests.Expression,
Expression.Lambda<Func<Request, bool>>(predicate, new ParameterExpression[] { pe }));
IQueryable<Request> result = _db.Requests.Provider.CreateQuery<Request>(where);
var list = result.ToList();
如果您有任何问题,请告诉我
我不是 100% 确定你的 Request 对象是什么样子的,但我会使用 PredicateBuilder。这是您的搜索功能的示例。
IQueryable<Request> SearchRequests (string searchTerm, string specField, string searchType)
{
var predicate = PredicateBuilder.False<Request>();
//These two are not correct and I need help writing these
if (searchType == "Fuzzy" && searchTerm != "" && specField != "None")
{
predicate = predicate.Or (r => r.(specField).Contains(searchTerm));
}
if (searchType == "Literal" && searchTerm != "" && specField == "None")
{
predicate = predicate.Or (r => r.Equals(searchTerm));
}
return new IntegrationDBEntities()
.Requests
.AsExpandable()
.Where(predicate);
}
那么您的方法可能如下所示:
Public PartialViewResult _Search(string searchTerm, string specField, string searchType)
{
ViewData.Model = SearchRequests(searchTerm, specField, searchType).ToList();
Return partialView();
}
更新:我添加了来自 LinqPad 的工作示例。您需要稍微修改它才能使其适用于 EntityFramework
.
void Main()
{
var results = SearchRequests("Fuzzy", "later").ToList();
results.Dump();
var results2 = SearchRequests("Literal", "Test me now").ToList();
results2.Dump();
}
// Define other methods and classes here
public class Request
{
public int Id {get;set;}
public string SearchTerm {get;set;}
}
public IQueryable<Request> LoadData()
{
var list = new List<Request>();
list.Add(new Request {Id = 1, SearchTerm = "Test me now"});
list.Add(new Request {Id = 2, SearchTerm = "Test me later"});
list.Add(new Request {Id = 3, SearchTerm = "Test me maybe"});
list.Add(new Request {Id = 4, SearchTerm = "Test me now"});
list.Add(new Request {Id = 5, SearchTerm = "Test me later or never"});
list.Add(new Request {Id = 6, SearchTerm = "Test me maybe or today"});
return list.AsQueryable();
}
public IQueryable<Request> SearchRequests (string searchType, string searchTerm)
{
var data = LoadData();
var predicate = PredicateBuilder.False<Request>();
//These two are not correct and I need help writing these
if (searchType == "Fuzzy")
{
predicate = predicate.Or(r => r.SearchTerm.Contains(searchTerm));
}
if (searchType == "Literal")
{
predicate = predicate.Or (r => r.SearchTerm.Equals(searchTerm));
}
return data.Where(predicate);
}
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);
}
}
首次搜索结果:
Id SearchTerm
2 Test me later
5 Test me later or never
第二次搜索结果:
Id SearchTerm
1 Test me now
4 Test me now
我在 MVC 中创建了一个搜索工具。用户将 searchTerm 字符串键入搜索框和 selects 选项以从 2 个下拉 select 列表中进行搜索。在第一个列表中,用户 selects "Fuzzy" 或 "Literal" 用于搜索类型,在第二个列表中,用户可以 select 搜索特定字段,specField。单击搜索按钮后,3 个字符串值将传递给控制器。
我正在尝试编写一个 "if" 语句,该语句根据传入控制器的这 3 个字符串值查询 Entity Framework 数据库模型。如何编写使用这些值的查询?
这就是我所拥有的。我知道查询没有写正确:
Public PartialViewResult _Search(string searchTerm, string specField, string searchType)
{
//This works to populate the table with the entire DB
_db = new IntegrationDBEntities();
var request = (from r in _db.Requests
select r).ToList();
//These two are not correct and I need help writing these
if (searchType == "Fuzzy" && searchTerm != "" && specField != "None")
{
request = (from r in _db.Requests
where r.(specField).Contains(searchTerm)
select r).ToList();
}
if (searchType == "Literal" && searchTerm != "" && specField == "None")
{
request = (from r in _db.Requests
where r.Equals(searchTerm)
select r).ToList();
}
ViewData.Model = request;
Return partialView();
}
希望这没有错误:
ParameterExpression pe = Expression.Parameter(typeof(Request), "Request");
Expression property = Expression.Property(pe, specField);
Expression predicate = null;
Expression srch = Expression.Constant(searchTerm, typeof(string));
if(searchType == "Fuzzy")
{
MethodInfo contains = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
predicate = Expression.Call(property, contains, srch);
}
else
{
predicate = Expression.Equal(property, srch);
}
MethodCallExpression where = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { _db.Requests.ElementType },
_db.Requests.Expression,
Expression.Lambda<Func<Request, bool>>(predicate, new ParameterExpression[] { pe }));
IQueryable<Request> result = _db.Requests.Provider.CreateQuery<Request>(where);
var list = result.ToList();
如果您有任何问题,请告诉我
我不是 100% 确定你的 Request 对象是什么样子的,但我会使用 PredicateBuilder。这是您的搜索功能的示例。
IQueryable<Request> SearchRequests (string searchTerm, string specField, string searchType)
{
var predicate = PredicateBuilder.False<Request>();
//These two are not correct and I need help writing these
if (searchType == "Fuzzy" && searchTerm != "" && specField != "None")
{
predicate = predicate.Or (r => r.(specField).Contains(searchTerm));
}
if (searchType == "Literal" && searchTerm != "" && specField == "None")
{
predicate = predicate.Or (r => r.Equals(searchTerm));
}
return new IntegrationDBEntities()
.Requests
.AsExpandable()
.Where(predicate);
}
那么您的方法可能如下所示:
Public PartialViewResult _Search(string searchTerm, string specField, string searchType)
{
ViewData.Model = SearchRequests(searchTerm, specField, searchType).ToList();
Return partialView();
}
更新:我添加了来自 LinqPad 的工作示例。您需要稍微修改它才能使其适用于 EntityFramework
.
void Main()
{
var results = SearchRequests("Fuzzy", "later").ToList();
results.Dump();
var results2 = SearchRequests("Literal", "Test me now").ToList();
results2.Dump();
}
// Define other methods and classes here
public class Request
{
public int Id {get;set;}
public string SearchTerm {get;set;}
}
public IQueryable<Request> LoadData()
{
var list = new List<Request>();
list.Add(new Request {Id = 1, SearchTerm = "Test me now"});
list.Add(new Request {Id = 2, SearchTerm = "Test me later"});
list.Add(new Request {Id = 3, SearchTerm = "Test me maybe"});
list.Add(new Request {Id = 4, SearchTerm = "Test me now"});
list.Add(new Request {Id = 5, SearchTerm = "Test me later or never"});
list.Add(new Request {Id = 6, SearchTerm = "Test me maybe or today"});
return list.AsQueryable();
}
public IQueryable<Request> SearchRequests (string searchType, string searchTerm)
{
var data = LoadData();
var predicate = PredicateBuilder.False<Request>();
//These two are not correct and I need help writing these
if (searchType == "Fuzzy")
{
predicate = predicate.Or(r => r.SearchTerm.Contains(searchTerm));
}
if (searchType == "Literal")
{
predicate = predicate.Or (r => r.SearchTerm.Equals(searchTerm));
}
return data.Where(predicate);
}
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);
}
}
首次搜索结果:
Id SearchTerm
2 Test me later
5 Test me later or never
第二次搜索结果:
Id SearchTerm
1 Test me now
4 Test me now