当前记录没有元素时,MVC dbContext查找父记录

时间:2012-09-30 12:56:26

标签: c# asp.net-mvc entity-framework-4.1 dbcontext

我是MVC / C#初学者,所以请轻松一点。

我有一个现有数据库,其中客户有零个或多个项目。我已经从ADODB实体数据模型和dbContext代码生成器构建了一个ASP.Net项目。

我有一位客户:Joe Bloggs(ID = 7)。我点击表格中的Joe Bloggs的“项目”链接,查看他的项目。他没有。我想为他创建一个项目,所以我在项目控制器上调用Create动作。

我需要将Joe Bloggs ID传递给Create操作有三个原因(可能没有必要 - 如果需要请赐教)

  1. 因为这是Joe Bloggs的项目,我需要将ID = 7传递给控制器​​,这样我就可以在为创建视图生成模型数据时为他设置默认的客户ID

  2. 当我点击“创建”视图上的“取消”按钮时,我想回到基于Joe博客的最初过滤的项目视图

  3. 当我点击保存时,我想回到基于Joe Bloggs的最初过滤的项目视图。

  4. 无论如何,如果我有一个或多个Joe Bloggs项目,那么我可以使用下面的这个怪物从视图中的模型数据中访问他的id:

    <input type="button" title = "New Project" value="New Project" onclick="location.href='@Url.Action("Create", new { id = Model.First().Customer_ID })'" />
    

    问题在于:如果他没有任何项目,Model.First()不会返回任何内容,因此我找不到'父'Customer_ID记录。

    我使用dbContext生成模型类(这是数据优先开发)。有些东西告诉我,我可以扩展这些类或创建一个新的类以允许上述情况。

    我目前的解决方法是使用ViewBag从查看器传递各种ID和字符串&gt;控制器就像一个烫手山芋,但这意味着如果得到三个深度(Customer&gt; Proejct&gt; Task),并且我想在任务上显示客户名称,我已经通过了两次。闻起来。

    我注意到项目索引视图中的下拉列表中有客户。这是我的代码:

    @Html.DropDownList("Customer_ID", null, "Select a Customer to Filter", new { @onchange = "this.form.submit();" })
    

    我可能能够将它从那里劈开但是我真的希望能够从一个可能有两到三个深度并远离此下拉列表的类中遍历

    这是从dbContext

    生成的精简Customer和CustomerProject类
    public partial class Customer
    {
        public Customer()
        {
            this.Tasks = new HashSet<Task>();
            this.CustomerProjects = new HashSet<CustomerProject>();
        }
    
        public int Customer_ID { get; set; }
        public string Customer_Name { get; set; }
    
        public virtual ICollection<CustomerProject> CustomerProjects { get; set; }
    }
    
    public partial class CustomerProject
    {
        public CustomerProject()
        {
            this.Tasks = new HashSet<Task>();
            this.CustomerProjectTasks = new HashSet<CustomerProjectTask>();
        }
    
        public int CustomerProject_ID { get; set; }
        public int Customer_ID { get; set; }
        public string Project_Name { get; set; }
    
        public virtual ICollection<Task> Tasks { get; set; }
        public virtual Customer Customer { get; set; }
        public virtual ICollection<CustomerProjectTask> CustomerProjectTasks { get; set; }
    }
    

    我确信有一个明显的解决方案,但我的优势在于数据库和VB6,而不是C#

    在Mystere Man的建议下,我已经构建了一个ViewModel类,但是我遇到了一些麻烦:

    以下是我的模型类文件中的内容(据我所知,这只是现有项目实体的包装器):

    namespace zzz.Models
    {
        using System;
        using System.Collections.Generic;
    
        public class ProjectsViewModel
        {
            public int Customer_ID { get; set; }
            public ICollection<CustomerProject> CustomerProjects;
        }
    }
    

    以下是我的控制器的Index操作中的内容(我已将我现有的Project集合添加到新的ViewModel类中):

        public ViewResult Index(int pCustomer_ID = 0, string pProjectName_Filter = "")
        {
    
            // Set up drop down
            ViewBag.Customer_ID = new SelectList(db.Customers.OrderBy(x => x.Customer_Name), "Customer_ID", "Customer_Name");
            //ViewBag.Selected_Customer_ID = Customer_ID;
    
            // If no parameters entered, show nothing
            // Otherwise optionally filter each parameter
            var projects = from p in db.CustomerProjects
                orderby p.Active, p.Project_Order
                where
                (p.Project_Name.Contains(pProjectName_Filter) || pProjectName_Filter.Equals("")) &&
                (p.Customer_ID == pCustomer_ID || pCustomer_ID.Equals(0)) &&
                !(pCustomer_ID.Equals(0) && pProjectName_Filter.Equals(""))
                select p;
    
    
            var customerprojects = new ProjectsViewModel
            {
                Customer_ID = pCustomer_ID,
                CustomerProjects = projects.ToList()
            };
    
    
            return View(customerprojects);
        }
    

    以下是我视图的摘录(我试图遍历ViewModel类中的Project集合):

    @model IEnumerable<BistechPortal.Models.ProjectsViewModel>
    
    <table>
    @foreach (var item in Model.CustomerProjects)
    {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Project_Name)
        </td>
    </tr>
    }
    </table>
    

    当我运行Index操作时,在foreach行上我得到:

    'System.Collections.Generic.IEnumerable<zzzzPortal.Models.ProjectsViewModel>' does not contain a definition for 'CustomerProjects' "
    

    请翻译 - 为什么它不能在我的ViewModel中找到我的'CustomerProjects'集合?

1 个答案:

答案 0 :(得分:0)

这就是您不应该将实体对象直接传递给视图的原因。在大多数情况下,视图需要比定义的实体提供的信息更多的信息(或不同的信息)。

这就是View Models存在的原因。您将创建一个包含Customer_ID和项目(以及您需要的任何其他数据)的视图模型。然后,即使用户没有项目,也可以访问Customer_ID。

public class ProjectsViewModel {
     public int Customer_ID {get;set;}
     public List<CustomerProject> CustomerProjects;
}

然后将此新对象传递给您的视图。

(由OP添加:)

要将此对象传递给您的视图,您需要告诉视图它不再接受CustomerProjects类型的数据,(这需要我花费三个小时来计算)它不再是获得“可枚举”的数据。

所以在你看来改变

@model IEnumerable<Portal.Models.CustomerProjects>

@model Portal.Models.ProjectsViewModel

同样在您的视图中,您现在想要迭代Model.CustomerProject,因此请更改

@foreach (var item in Model)

@foreach (var item in Model.CustomerProjects)