将 ViewModel 映射到相关实体

Mapping ViewModel to related entities

我有一个具有多个属性的 ViewModel(用于多步向导的 VM):

public class CallViewModel
{
    [Key]
    [Column(Order = 0)]
    [HiddenInput(DisplayValue = false)]
    public System.Guid CallID { get; set; }

    [Required, Display(Name = "Call Date")]
    [DataType(DataType.Date)]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MM yyyy} г.")]
    public System.DateTime CallDate { get; set; }

    [Required, Display(Name = "Contract Number")]
    public string Number { get; set; }

    [Display(Name = "Date of Sampling"), DataType(DataType.Date)]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MM yyyy} г.")]
    public System.DateTime SampleActDate { get; set; }


    [Display(Name = "Date of the Contract"), DataType(DataType.Date)]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MM yyyy} г.")]
    public System.DateTime ContractDate { get; set; }

    [Required, Display(Name = "Cost Efficiency, %")]
    public decimal CostEfficiency { get; set; }

    [Required, Display(Name = "Document Type")]
    public string CallName { get; set; }

    //Representative
    [Required, Display(Name = "Second Name")]
    public string RepFamilyName { get; set; }

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

    [Required, Display(Name = "Middle Name")]
    public string RepMidName { get; set; }

    [Required, Display(Name = "Position")]
    public string RepPosition { get; set; }

    [Required, Display(Name = "Document")]
    public string DocType { get; set; }

    [Required, Display(Name = "Phone (###) ###-##-##")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:(###) ###-##-##}")]
    public string RepPhoneNumber { get; set; }

    //Customer
    [Required, Display(Name = "Judicial Status")]
    public string JudicialStatus { get; set; }

    [Required, Display(Name = "Customer Name")]
    public string CustomerName { get; set; }

    [Required, Display(Name = "Address")]
    public string CustomerAddress { get; set; }

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

    [Display(Name = "BIC")]
    public string BIC { get; set; }

    [Required, Display(Name = "PHone Number (###) ###-##-##")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:(###) ###-##-##}")]
    public string CustomerPhoneNumber { get; set; }

    [Required, Display(Name = "OKPO")]
    public int OKPO { get; set; }

    [Required, Display(Name = "Account)]
    public string CustomerBankAccount { get; set; }

    [Required, Display(Name = "Bank Branch")]
    public string BankBranch { get; set; }

    [Required, Display(Name = "Bank Address")]
    public string BranchAddress { get; set; }

    [Display(Name = "Bank Code")]
    public Nullable<int> BankCode { get; set; }

    [Display(Name = "Cell Phone Number")]
    public string MPhoneNumber { get; set; }

    //Person
    [Required, Display(Name = "Expert")]
    //public string Exp { get; set; }
    public Guid ExpID { get; set; }
    [Required, Display(Name = "Affidavit Number")]
    public int AffidavitNum { get; set; }

    [Required, Display(Name = "Affidavit Date"), 
        DataType(DataType.Date)]

    public System.DateTime AffidavitDate { get; set; }

    public List<ItemClass> ItemsList { get { return _items; } }

    private List<ItemClass> _items = new List<ItemClass>();

    public class ItemClass
    {  //Item

        public Guid ItemID { get; set; }

        [Required, Display(Name = "Item SubType")]
        public Guid ItemSubtype { get; set; }

        [Required, Display(Name = "Item Name")]
        public string ItemName { get; set; }

        [Required, Display(Name = "Producer")]
        public string ItemProducer { get; set; }

        [Required, Display(Name = "Quantity")]
        public int ItemQty { get; set; }

        [Display(Name = "Additionals")]
        public string Additional { get; set; }

        [Required, Display(Name = "Program Name")]
        public string ProgramNameShort { get; set; }

        [Required, Display(Name = "Calc Date")]
        public string calcDate { get; set; }

        [Required, Display(Name = "Calc Number")]
        public string calcNum { get; set; }

    }
}

我还有几个具有 1:n 关系的实体,例如

public partial class Call
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Call()
    {
        this.CallDetails = new HashSet<CallDetail>();
    }

    public System.Guid CallID { get; set; }
    public System.DateTime CallDate { get; set; }
    public System.Guid CustomerID { get; set; }
    public string DocNumber { get; set; }
    public int AffidavitNum { get; set; }
    public System.DateTime AffidavitDate { get; set; }
    public System.DateTime ContractDate { get; set; }
    public int CallStatus { get; set; }
    public string DocType { get; set; }
    public Nullable<decimal> Cost_Efficiency { get; set; }
    public System.DateTime SampleActDate { get; set; }
    public string CallName { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<CallDetail> CallDetails { get; set; }
    public virtual Customer Customer { get; set; }
}

public partial class CallDetail
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public CallDetail()
    {
        this.Orders = new HashSet<Order>();
    }

    public System.Guid CallID { get; set; }
    public System.Guid ItemID { get; set; }
    public int ItemQty { get; set; }
    public decimal ItemTestCost { get; set; }
    public System.Guid ProgramID { get; set; }

    public virtual Call Call { get; set; }
    public virtual Item Item { get; set; }
    public virtual Program Program { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Order> Orders { get; set; }
}

仅举几例。 在 [HttpPost] public ActionResult Create (CallViewModel callViewModel) 方法中,我应该将 ViewModel 映射到那些实体。我知道 Automapper 是执行它的最佳方法之一,但我仍然需要了解正确映射 VM 和相关实体的原则(也欢迎使用 Automapper 示例 :)),尤其是如何处理导航属性(我'主要担心 ID 属性)。您能否展示执行它的最佳(或模板)实践?请尽可能详细。 提前致谢。

举个例子:

public class ModelClass
{
    public Guid Id { get; set; }

    public ChildModel ChildModel { get; set; }
}

public class ViewModelClass
{
    public Guid Id { get; set; }

    public ChildModel ChildModel { get; set; } = new ChildModel();
}

public class ChildModel
{
    public Guid Id { get; set; }
}

如果你想将你的视图模型映射到你的模型,你可以这样做:

    [HttpPost] 
    public ActionResult Create (CallViewModel callViewModel) {
        var model = new ModelClass;

        model.Id = callViewModel.Id;
        model.ChildModel = callViewModel.ChildModel;

        _context.Add(model);
        _context.SaveChanges();

        return RedirectToAction("Index");
    }

对于 automapper 的使用,我建议你 read AutoMapper 文档 :)