【问题标题】:Am I mixing up controller / model in this MVC implementation我是否在这个 MVC 实现中混淆了控制器/模型
【发布时间】:2013-07-20 22:35:35
【问题描述】:

MVC 新手,请原谅这个问题。

我创建了两个模型,ObservationStaffMember。一名工作人员进行了一次观察,我根据观察记录记录了 StaffMember 的 ID (GUID)。显示结果时,我希望显示 StaffMember.FullName 而不是 StaffMember.StaffMemberId

我已经通过使用以下模型实现了这一点:

public class Observation
{
    public Guid ObservationId { get; set; }
    public string Observer { get; set; }
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
    public DateTime ObservationDate { get; set; }
    public Guid StaffMemberId { get; set; }
    public int? ObservationGrade { get; set; }
    public virtual IEnumerable<StaffMember> StaffMembers { get; set; }

    public string StaffMemberName
    {
        get
        {
            var db = new ObservationTrackerContext();
            var staffMember = db.StaffMembers.FirstOrDefault(s => s.StaffMemberId == StaffMemberId);

            return staffMember != null ? staffMember.FullName : "Missing entry or error";
        }
    }
}

我有点担心我将模型的定义与数据库交互混淆了。这是对 MVC 模式的正确使用还是我应该以不同的方式这样做?

提前感谢任何 cmets 或建议。

【问题讨论】:

  • 控制器与数据库交互无关。在 MVC 模式中,它们是“模型”的一部分。也就是说,模型通常不仅仅是数据结构/实体类——通常有一个“数据访问”或“业务逻辑”层来执行数据操作,而控制器只是选择要运行的业务逻辑操作。跨度>
  • 也就是说,StaffMemberName 属性是不确定的 - 它涉及在已经检索到 Observation 实体之后运行数据库访问代码。如果没有别的,这是低效的。通常,您应该尝试让控制器获取数据结构,您只需导航到已加载的所需数据,例如使用Include()

标签: asp.net-mvc model-view-controller


【解决方案1】:

我假设您指的是最后一部分:

public string StaffMemberName
    {
        get
        {  var db = new ObservationTrackerContext();
            var staffMember = db.StaffMembers.FirstOrDefault(s => s.StaffMemberId == StaffMemberId);    
        return staffMember != null ? staffMember.FullName : "Missing entry or error";
        }
     }

我个人认为,虽然这可能有效,但它并不是最干净的做事方式。 我尽可能保持我的视图模型简洁明了,所以基本上只是一堆带有{get;set;} 的属性。

您如何设置此视图模型中的其他属性?

有什么理由不能像设置StaffMemberId 那样设置StaffMemberName 吗?

我个人会将所有逻辑(除了DataAnnotations 等)排除在视图模型之外。 更好的一步是将您的逻辑放在控制器方法中。 更好的是,放置一个额外的层,您可以在其中进行所有数据库检索。

通过这种方式,控制器和视图保持尽可能简单。

在您的情况下,我会做以下事情,我会像这样创建一个 MemberService:

public class MemberService
{
public string GetStaffMemberById(Guid Id)
{
    var db = new ObservationTrackerContext();
    var staffMember = db.StaffMembers.FirstOrDefault(s => s.StaffMemberId == StaffMemberId);return staffMember != null ? staffMember.FullName : "Missing entry or error";    
    return staffMember;
} 
}

然后,在控制器中,设置视图模型:

public ActionResult GetInformation(Guid id)
{
var vm = new StaffMemberViewModel();
vm.StaffMemberName = memberService.GetStaffMemberById(id);
return View(vm);
}

通过这种方式,您的视图模型可以更改为

public string StaffMemberName {get;set;}

编辑:我更关注视图模型中的数据库检索方面,但@Miller Koijam 也提出了一个很好的观点,将这些不同的模型封装到一个复合视图模型中。

编辑号 2:您似乎返回的是纯数据库对象,这在大型项目中并不是真正可维护的。您应该将这些数据库对象“转换”或“投影”到视图模型中。

this link gives a pretty good explanation on how to do this

【讨论】:

  • 感谢您的回复。我想我也许可以将这个逻辑删除到一个单独的类中——我喜欢把它放到控制器中的想法。在您的示例中,您引用 StaffMemberViewModel 作为视图返回 - 我想要实现的是在 Observation 视图中 - 只需查找名称与已记录在数据库中的 GUID 匹配的 StaffMember 的名称反对这个Observation
  • 您如何/在哪里设置/填充当前的观察视图模型?
  • 在我的控制器中,我有以下内容(这是一个实体框架代码第一个应用程序 - 我的第一个):private ObservationTrackerContext db = new ObservationTrackerContext(); // // GET: /Observation/ public ActionResult Index() { return View(db.Observations.ToList()); }
  • public ActionResult Index() { Return View(db.Observations.ToList()); } - 无法在 cmets 中正确设置格式。
  • 嗯,你正在做的是返回你的“纯”数据库返回值,这也不是一个真正的最佳实践。我会尝试制作一个单独的复合视图模型,就像@Miller Koijam 说的那样。将您的数据库代码放在一个单独的类中,并用数据库中的数据填充您的视图模型,然后返回该数据,而不是纯数据库对象。
【解决方案2】:

最好的办法是将每个模型分成不同的类。 如果存在一对一的关系,那么您的模型就可以了。 你可以有一个类似的方法

GetStaffMemberById(Guid Id)
{
     //Add your code to fetch the StaffMember
}

如果存在一对多关系 您需要在更大的模型中显示两个模型的关联,您可以使用名为 StaffMemberObeservation/OberservationStaffMember 的复合模型作为父子的关联性。 如果您的 StaffMember 有多个 Observation 而不是

public class StaffMemberObeservation
{
public Observation { get; set; }
public IList <StaffMember>{ get; set; }
}

如果您的 Observation 的工作人员不止一名

public class ObersavtionStaffMember
{


   public Staff Member{ get; set; }
   public IList <Observation> { get; set; }

}

【讨论】:

  • 我认为这可能是我应该采用的方式。一个StaffMember 可以有多个观察值。我希望将其保持为更简单的结构,因为我真正需要做的就是查找 StaffMember 的名称,其 GUID 已针对 Observation 记录。
  • 如果应该是 IList 而不是 。观察也是如此。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-22
  • 1970-01-01
  • 2010-12-28
  • 1970-01-01
相关资源
最近更新 更多