【问题标题】:Should I put a "required" data annotation in Model or viewModel? [closed]我应该在模型或视图模型中放置“必需”数据注释吗? [关闭]
【发布时间】:2016-12-23 03:50:34
【问题描述】:

我不确定如何设置我的数据模型。

我正在使用:MVC 5、EF 6.1.3

我有一个 Model 类,它有几个属性(装饰有几个“必需”数据注释属性以反映创建的数据库表),这些字段是使用我的控制器中的 viewModel 填充的。

[HttpPost]
public ActionResult Create(CreateRequestViewModel viewModel)
{
    if (!ModelState.IsValid)
    {
        viewModel.Affiliations = _context.Affiliations.ToList();
        viewModel.Issues = _context.Issues.ToList();
        return View(viewModel);
    }

    var request = new Request
    {
        RequestDate = DateTime.Today,
        Status = "Open",
        FirstName = viewModel.FirstName,
        LastName = viewModel.LastName,
        AffiliationId = viewModel.Affiliation,
        IssueId = viewModel.Issue,
        LastModificationDate = DateTime.Now,
        RequestTypeId = 2,
    };

    _context.Requests.Add(request);
    _context.SaveChanges();

    return View("Success");
}

模型类:

public class Request
{
    [Display(Name = "Request ID")]
    public int Id { get; set; }

    [Required]
    [Display(Name = "Request Date")]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime RequestDate { get; set; }

    [Required]
    public string Status { get; set; }

    [Required]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }

    [Display(Name = "Last Modified")]
    public DateTime LastModificationDate { get; set; }

    //navigations properties
    public Affiliation Affiliation { get; set; }
    public Issue Issue { get; set; }
    public RequestType RequestType { get; set; }

    //foreign keys
    [Display(Name = "Affiliation")]
    public byte AffiliationId { get; set; }
    [Display(Name = "Issue")]
    public int IssueId { get; set; }
    [Display(Name = "Request Type")]
    public byte RequestTypeId { get; set; }


}

CreateRequestViewModel 类:

public class CreateRequestViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string FullName { get; set; }


    public IEnumerable<Affiliation> Affiliations { get; set; }
    public IEnumerable<Issue> Issues { get; set; }

    [Required(ErrorMessage = "Required!")]
    public byte Affiliation { get; set; }
    [Required(ErrorMessage = "Required!")]
    public int Issue { get; set; }
}

但是,如果我想更新数据库表中反映模型类的某些字段,我必须加载所有必需的属性,然后再次保存它们,因为“必需”数据注释。问题是我只需要更新一些但不是所有属性(例如:我不会更改 FirstName 或 LastName 值)。

我的问题:我应该从我的 Model 类中删除“必需”数据注释属性并在 viewModel 上设置这些数据注释以供用户输入吗?如果我这样做了,那么我将丢失数据库表上字段的“非空”约束,但它是通过我的模型视图强制执行的。还是应该在我的 dbcontext 上调用 .SaveChanges() 之前加载整个 Model 对象并再次保存所有属性?

注意:我在我的模型和视图模型中删除了几个额外的属性以缩短这里的代码。

编辑; 我最终实现了以下代码以避免更改模型。它似乎工作正常。

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Details(DetailsViewModel request)
    {

        var model = new Request
        {
            Id = request.Id,
            RequestDate = request.RequestDate,
            Status = request.Status,
            FirstName = request.FirstName,
            LastName = request.LastName,
            LastModificationDate = DateTime.Now,
            AffiliationId = request.AffiliationId,
            IssueId = request.IssueId,
            RequestTypeId = request.RequestTypeId,

        };

        _context.Requests.Attach(model);
        var entry = _context.Entry(model);
        entry.Property(e => e.Status).IsModified = true;
        entry.Property(e => e.AffiliationId).IsModified = true;
        entry.Property(e => e.IssueId).IsModified = true;
        entry.Property(e => e.RequestTypeId).IsModified = true;
        entry.Property(e => e.LastModificationDate).IsModified = true;

        _context.SaveChanges();

        return RedirectToAction("Requests");

【问题讨论】:

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


    【解决方案1】:
    1. 如果 First Name(和其他在 Model 中标记为必填的属性)是必填字段,那么您应该装饰您的 Model(以便在表中,该字段将被标记为非空)以及 ViewModel (用于 ModelState 验证并在 ui 中显示错误消息,以防您使用 jQuery 验证器)和必需的属性

    2. 为了在更新时只更新少数属性,您不必加载整个实体,而是可以将特定属性的状态标记为已修改。

      var entry = context.Entry(你的实体); entry.Property(e=> e.YourChangedProperty1).IsModified = true; entry.Property(e=> e.YourChangedProperty2).IsModified = true; context.SaveChanges();

    【讨论】:

    • 所以我最终改为这样做:它可以工作,但不确定是否合适,因为我仍然会带来视图传递的所有属性。 _context.Requests.Attach(模型); var entry = _context.Entry(model); entry.Property(e => e.Status).IsModified = true; entry.Property(e => e.AffiliationId).IsModified = true; entry.Property(e => e.IssueId).IsModified = true; entry.Property(e => e.RequestTypeId).IsModified = true; entry.Property(e => e.LastModificationDate).IsModified = true; _context.SaveChanges();
    • @Joe Cuevas:如果您的请求实体很大并且您只需要更新一些属性,这就是我所做的。但这可能是个人选择。当我有疑问时,我通常会验证 profiler/intellitrace 中生成的查询,以检查 EF 生成的查询是否接近我们的想法。
    【解决方案2】:

    将 required 放在你的数据模型中有意义的地方。如果数据实体总是需要名字,把它放在那里。

    如果您的视图模型不需要名字,请不要放在那里。 如果你需要你的用户输入来包含一个属性,那么在你的虚拟机中把 required 放在那个属性上。

    加载你的实体来更新它是非常好的。将 vm 更改为“修复”某些数据实体不是。

    【讨论】:

      猜你喜欢
      • 2018-03-13
      • 2011-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-26
      • 2017-10-26
      • 2023-04-03
      • 1970-01-01
      相关资源
      最近更新 更多