在其他表

时间:2017-10-31 00:14:23

标签: c# asp.net-mvc

我是c#和MVC的新手。我已经看到了一些与我的问题类似的问题,但没有任何帮助我解决这个问题。我正在寻找更具体的指导。

我正在尝试使用相关表格中的特定列过滤搜索结果。我正在显示Shifts的列表。每个班次都有StoreNum作为外键。 StoreNumStores表的主键。 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; }

感谢您对我和我的代码的任何其他部分提供任何指导和反馈......这有助于我学习!

2 个答案:

答案 0 :(得分:0)

我认为您希望首先加入ShiftStore 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。我确信有比我更优雅的解决方案,但这很有效。