我是c#和MVC的新手。我已经看到了一些与我的问题类似的问题,但没有任何帮助我解决这个问题。我正在寻找更具体的指导。
我正在尝试使用相关表格中的特定列过滤搜索结果。我正在显示Shifts
的列表。每个班次都有StoreNum
作为外键。 StoreNum
是Stores
表的主键。 Stores
表包含一个名为Area
的列。我希望用户能够点击复选框并将结果过滤到Area
。
这是我的控制器中的方法(我省略了一些当前有效且似乎无关的代码):
[HttpGet]
public ActionResult OpenShiftList(DateTime? searchStartDate = null, DateTime? searchEndDate = null, DateTime? searchStartTime = null, DateTime? searchEndTime = null, Boolean? searchStore = null, Boolean? searchArea = false, Boolean? searchDistrict = false)
{
var thisStore = User.StoreNum();
var data =
from s in db.Shifts
select s;
if (searchDistrict == true)
{
data = data.Where(s => db.Stores.Select(x => x.District.Where(x.StoreNum == thisStore)));
}
data = data.Where(s => s.IsCovered.Equals(false));
return View(data.ToList());
}
我收到错误"Argument 2: cannot convert 'bool' to 'System.Func<char, bool>'
作为参考,我的视图中的HTML与此相关:
<div class="col-md-2 well">
<div class="form-group">
@using (Html.BeginForm("OpenShiftList", "Shifts", FormMethod.Get))
{
<p>
Date @Html.TextBox("searchStartDate", "", new { @class = "date-picker" }) to @Html.TextBox("searchEndDate", "", new { @class = "date-picker" })
</p><p>
Start Time @Html.TextBox("searchStartTime", "", new { @class = "timepicker" })
</p><p>
End Time @Html.TextBox("searchEndTime", "", new { @class = "timepicker" })
</p><p>
My Store @Html.CheckBox("searchStore")
</p><p>
My District @Html.CheckBox("searchDistrict")
</p><p>
My Area @Html.CheckBox("searchArea")
</p><p>
<input type="submit" value="Search" class="btn btn-primary btn-md" />
</p>
}
</div>
</div>
</div>
有没有办法按照我目前设置的方式实现这个过滤目标?我需要使用viewmodel吗?
修改
这是Shift
public int ShiftID { get; set; }
[DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode =true)]
public System.DateTime Date { get; set; }
[DisplayFormat(DataFormatString = "{0:HH:mm tt}", ApplyFormatInEditMode = true)]
[DataType(DataType.Time)]
[Display(Name="Start Time")]
public System.DateTime StartTime { get; set; }
[DisplayFormat(DataFormatString = "{0:HH:mm tt}", ApplyFormatInEditMode = true)]
[DataType(DataType.Time)]
[Display(Name ="End Time")]
public System.DateTime EndTime { get; set; }
[Display(Name ="Store Number")]
public string StoreNum { get; set; }
public string Id { get; set; }
[Display(Name ="Covered")]
public bool IsCovered { get; set; }
以下是Store
的课程:
[Display(Name="Store Number")]
public string StoreNum { get; set; }
[Display(Name = "Store Name")]
public string StoreName { get; set; }
[Display(Name = "Store Address")]
public string StreetAddr { get; set; }
public string City { get; set; }
public string State { get; set; }
public string District { get; set; }
public string Area { get; set; }
感谢您对我和我的代码的任何其他部分提供任何指导和反馈......这有助于我学习!
答案 0 :(得分:0)
我认为您希望首先加入Shift
和Store
StoreNum
以获取每个商店的转变。您可以在加入之前构建where子句。
因为您要查询数据库,我们需要构建表达式。
Expression<Func<StoreShift, bool>> hasStoreNum = (s) => s.Shift.StoreNum == storeNum;
Expression<Func<StoreShift, bool>> hasArea = (s) => s.Shift.Area == s.Store.Area;
Expression<Func<StoreShift, bool>> hasDistrict = (s) => s.Shift.District == s.Store.District;
var predicates = new List<Expression<Func<StoreShift, bool>>>();
predicates.Add(hasStoreNum);
if (searchArea)
{
predicates.Add(hasArea);
}
if (searchDistrict)
{
predicates.Add(hasDistrict);
}
var query = from shift in db.Shifts
join store in db.Stores on shift.StoreNum equals store.StoreNum
select new StoreShift { Store = store, Shift = shift };
var result = query.WhereAny(predicates).Select(s => s.Shift);
你需要一些辅助类
public class StoreShift
{
public Store Store { get; set; }
public Shift Shift { get; set; }
}
我获得了here
以下课程的实施public static class QueryableExtensions
{
public static IQueryable<T> WhereAny<T>(this IQueryable<T> source, IEnumerable<Expression<Func<T, bool>>> predicates)
{
if (predicates == null || !predicates.Any()) return source;
var predicate = predicates.Aggregate((a, b) => Expression.Lambda<Func<T, bool>>(
Expression.Or(a.Body, b.Body.ReplaceParameter(b.Parameters[0], a.Parameters[0])),
a.Parameters[0]));
return source.Where(predicate);
}
}
public static class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Source ? Target : base.VisitParameter(node);
}
}
}
这是我能找到的最简单的Expression构建器实现。还有一些NuGet库可以帮助您动态构建表达式。
答案 1 :(得分:0)
我设法使用Jasen执行连接的想法解决了这个问题。
var GetArea = from shift in db.Shifts
join store in db.Stores on shift.StoreNum equals store.StoreNum
where store.StoreNum == thisStore
select store.Area;
var thisArea = GetArea.First();
这允许我为用户Area
存储Store
。然后...
if (searchArea == true)
{
data = from shift in db.Shifts
join store in db.Stores on shift.StoreNum equals store.StoreNum
where store.Area.Contains(thisArea)
select shift;
}
这允许我过滤Area
。我确信有比我更优雅的解决方案,但这很有效。