如何从数据库中过滤属性

时间:2017-11-15 17:19:18

标签: c# asp.net-mvc entity-framework visual-studio-2017

我正在使用Visual Studio 2017并使用Entity Framework创建了一个标准的ASP.NET / MVC项目,最后包含了一个本地数据库。 我有课程"课程"和"类别"。一门课程可以有一个类别,一个类别可以在许多课程中。 (n:1关系)

我的模型适用于我的课程:

namespace project.Models
{
    public class Course
    {
        public int ID { get; set; }        
        public int CategoryID { get; set; }
        public string Name { get; set; }
        public string  Description { get; set; }

        public virtual CourseCategory CourseCategory { get; set; }

    }

courseCategory.cs的模型是:

    namespace project.Models
{
    public class CourseCategory
    {
        public int ID { get; set; }
        public string Name { get; set; }

        public virtual ICollection<Course> Course { get; set; }
    }
}

观点是:

@model IEnumerable<Models.Courses>

@{
    ViewData["Title"] = "Index";
}

<h2>Index</h2>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
                <th>
                    @Html.DisplayNameFor(model => model.ID)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.CategoryID)
                </th>                    
                <th>
                    @Html.DisplayNameFor(model => model.Name)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Description)
                </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.ID)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.CategoryID)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Description)
            </td>
            <td>
                <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
                <a asp-action="Details" asp-route-id="@item.ID">Details</a> 
                <a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
            </td>
        </tr>
}
    </tbody>
</table>

从这两个类派生,我自动创建了控制器和视图。我做&#34; add-migration -xx&#34;和&#34;更新数据库&#34;我的应用程序是可运行的。 我打开&#34; http://localhost/courses&#34;我有我的课程列表(包括课程的给定类别),可以添加,移动删除等... 如果我查看我的数据库/表,我可以看到正确的主键和外键。它有效......

但是现在,我希望增加过滤课程的可能性。我需要额外的一部分,我的类别列在其中,如果我点击其中一个类别,我想要一个新的结果列表,所有课程与点击的类别。

我如何实现它以及我必须修改代码的位置? 我试图修改CourseController.cs

  // GET: Course
    public async Task<IActionResult> Index()
    {
        return View(await _context.Course.ToListAsync());
    }

我想我在这里需要一些思考,比如表中主键的比较?

1 个答案:

答案 0 :(得分:1)

这就是你需要的

  1. 您的视图中的下拉菜单,用户可以在其中选择类别
  2. 更改您的操作方法,它将接受所选类别并获取该类别下的课程。
  3. 有多种方法可以做到这一点。这就是我将如何做到的。

    我不想在我的UI层中混合ORM创建的实体类。所以我创建了一个特定于视图的视图模型

    public class CourseListVm
    {
       public int? CategoryId { set;get;}
       public List<SelectListItem> Categories { set;get;}
       public IEnumerable<CourseVm> Courses { set;get;}
       public CourseListVm()
       {
           this.Courses = new List<CourseVm>();
       }
    }
    public class CourseVm
    {
       public int Id { set;get;}
       public string Name { set;get;}
    }
    

    现在,在您的操作方法中,创建一个此对象,将可用类别从数据库加载到Categories属性。我们将向action方法添加一个参数,并检查是否有选定catetory的值(来自ui),如果是,我们将在填充Courses属性时进行过滤

    public async Task<IActionResult> Index(int? categoryId)
    {
        var vm=new CourseListVm();
        //Populate the catetory list so that we can use that in UI to build the dropdown
        vm.Categories = _context.Categories
                                .Select(a => new SelectListItem() {Value = a.Id.ToString(), 
                                                                   Text = a.Name})
                                .ToList();
        List<Course> courseList = new List<Course>();
        if(categoryId==null)
        {
          courseList = await _context.Course.ToListAsync()
        }
        else
        {
          courseList = await _context.Course
                         .Where(a=>a.CategoryId==categoryId.Value)
                         .ToListAsync()
        }
        vm.Courses = GetCourseVms(courseList);
        return View(vm);
    }
    private IEnumerable<CourseVm> GetCourseVms(IEnumerable<Course> courses)
    {
        return courses.Select(a=>new CourseVm { Id=a.Id, Name =a.Name});
    }
    

    我使用GetCourseVms方法将Course实体映射到CourseVm视图模型对象。如果您愿意,可以使用Auto mapper等库来实现。

    现在,在您的视图中,强烈键入CourseListVm,我们将使用DropDownListFor辅助方法呈现类别的下拉列表。如果您正在使用asp.net核心应用程序,则可以使用Select tag helper to render the dropdown

    @model CourseListVm
    @using (Html.BeginForm("Index", "Courses",FormMethod.Get))
    {
        @Html.DropDownListFor(a=>a.CategoryId,Model.Categories,"All")
        <button type="submit">Filter</button>    
    }
    @foreach (var p in Model.Courses)
    {
        <p>@p.Id</p>
        <p>@p.Name</p>
    }
    

    当用户选择一个类别并单击提交按钮时,表单将被提交到URL中具有所选类别ID的索引操作,操作方法代码将使用该操作创建要过滤的课程的过滤集合在视图中。