Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在MVC(CRUD)中创建模型的最佳实践_C#_Asp.net Mvc_Model View Controller_Asp.net Mvc Viewmodel - Fatal编程技术网

C# 在MVC(CRUD)中创建模型的最佳实践

C# 在MVC(CRUD)中创建模型的最佳实践,c#,asp.net-mvc,model-view-controller,asp.net-mvc-viewmodel,C#,Asp.net Mvc,Model View Controller,Asp.net Mvc Viewmodel,因此,我们向团队中添加了一名新的程序员,他对如何在MVC中创建模型有一些想法,这与我们以前创建模型的方式不同。比如说,我们有一个系统,其中用户提交文档请求,系统中有一个页面,用户在其中计算完成该文档请求的费用。此费用创建页面可以键入有关费用和相关发票的一些数据。用户可以添加发票行项目,并使用这些项目自动计算费用总额。在这种情况下,我们通常会创建如下所示的模型 public class Fee { public virtual Guid RequestID { get; set;

因此,我们向团队中添加了一名新的程序员,他对如何在MVC中创建模型有一些想法,这与我们以前创建模型的方式不同。比如说,我们有一个系统,其中用户提交文档请求,系统中有一个页面,用户在其中计算完成该文档请求的费用。此费用创建页面可以键入有关费用和相关发票的一些数据。用户可以添加发票行项目,并使用这些项目自动计算费用总额。在这种情况下,我们通常会创建如下所示的模型

    public class Fee
{
    public virtual Guid RequestID { get; set; }
    public virtual Guid FeeID { get; set; }
    public string FeeTitle { get; set; }
    public decimal FeeAmount { get; set; }
    public DateTime? DueDate { get; set; }
    public decimal AmountPaid { get; set; }
    public Invoice Invoice { get; set; }
    public List<InvoiceLineItem> LineItems { get; set; }
}

public class Invoice
{ 
    // Additional Invoice Data (To, From, etc)
}

public class InvoiceLineItem
{
    public string LineItemTitle { get; set; }
    public int Quantity { get; set; }
    public decimal PricePerUnit { get; set; }
    public decimal Subtotal { get; set; }

}
我们的新程序员认为这不是一个好方法,因为不同的操作需要不同的数据。例如,当您创建费用时,您需要知道相应的请求ID。但是,当您更新费用时,您只需要知道费用ID。因此,当他创建模型时,他以这样一种方式创建模型,即存在多个继承层,以努力控制在服务层中更新并显示在视图中的数据。他的想法是,我们应该能够假设为事务传递的任何模型都应该使用其所有数据点,而不必根据具体情况猜测数据是什么

对我来说,这给我们的模型增加了大量不必要的复杂性,并且使得在其他模块上使用它们变得更加困难。下面是一个例子来说明这一点

 /// <summary>
/// This model is used to present data in a read fashion to the end user
/// </summary>
public class FeeViewModel : FeeModel_Create
{
    public string FullRequestNumber { get; set; }
    public decimal Balance { get; set; }
    public List<String> States { get; set; }
    public List<FeeAttachmentEditModel> Attachments { get; set; }
    public List<PaymentViewModel> Payments { get; set; }

}

/// <summary>
/// This model adds a request id to the fee update model because we need to know which request this fee is associated with
/// </summary>
public class FeeModel_Create : FeeModel_Update
{
    public Guid RequestID { get; set; }

}

/// <summary>
/// Represents the parameters required to update a fee
/// </summary>
public class FeeModel_Update
{
    public virtual Guid FeeID { get; set; }
    public decimal FeeAmount { get; set; }
    public DateTime? DueDate { get; set; }
    public string FeeTitle { get; set; }
    public decimal AmountPaid { get; set; }
    public List<MaterialList> MaterialTypes { get; set; }
    public List<InvoiceLineItem_Adhoc> LineItems { get; set; }
    public Invoice Invoice { get; set; }


    public void InjectValuesIntoInvoiceModel(Invoice Invoice)
    {
        Invoice.Description = this.Invoice.Description;
        Invoice.Terms = this.Invoice.Terms;
        Invoice.To_Name = this.Invoice.To_Name;
        Invoice.To_Address = this.Invoice.To_Address;
        Invoice.To_Address2 = this.Invoice.To_Address2;
        Invoice.To_City = this.Invoice.To_City;
        Invoice.To_State = this.Invoice.To_State;
        Invoice.To_Zip = this.Invoice.To_Zip;
        Invoice.From_Name = this.Invoice.From_Name;
        Invoice.From_Address = this.Invoice.From_Address;
        Invoice.From_Address2 = this.Invoice.From_Address2;
        Invoice.From_City = this.Invoice.From_City;
        Invoice.From_State = this.Invoice.From_State;
        Invoice.From_Zip = this.Invoice.From_Zip;
    }
}


public class InvoiceLineItem_Adhoc
{
    public string Type { get; set; }
    public string EnteredBy { get; set; }
    public decimal Quantity { get; set; }
    public decimal UnitCost { get; set; }
    public InvoiceLineItem ToLineItem(Guid InvoiceID)
    {
        var lineItem = new InvoiceLineItem();
        StaticValueInjecter.InjectFrom(lineItem, this);
        lineItem.InvoiceLineItemID = Guid.NewGuid();
        lineItem.InvoiceID = InvoiceID;
        lineItem.UserID = 1;
        return lineItem;
    }
}

public class PaymentViewModel
{
    public Guid RequestID { get; set; }
    public Guid FeeID { get; set; }
    public string FullRequestNumber { get; set; }
    public string FeeTitle { get; set; }
    public virtual Guid PaymentID { get; set; }
    public decimal PaymentAmount { get; set; }
    public Nullable<System.DateTime> DatePaid { get; set; }
}

public class FeeAttachmentEditModel
{
    public Guid RequestID { get; set; }
    public Guid FeeID { get; set; }
    public string FullRequestNumber { get; set; }
    public string FeeTitle { get; set; }
    public virtual System.Guid FeeAttachmentID { get; set; }
    public System.Guid AttachmentTypeID { get; set; }
    public string AttachmentName { get; set; }
    public byte[] Data { get; set; }
    public string Extension { get; set; }
    public string mimeType { get; set; }
    public string AttachmentBody { get; set; }
    public HttpPostedFileBase FileUpload { get; set; }
    public string FileName { get; set; }

    public bool HadError = false;
}

我只是想在这里找到一个答案,在MVC中创建模型的最佳实践是什么。您是否应该创建单独的模型,无论是通过继承部分类还是通过其他方式来适应您正在执行的创建、读取、更新或删除操作。或者最好有一个viewmodel转换为视图中显示的内容或从视图中传递的内容,并有逻辑过滤掉访问数据时来自视图模型的重要内容?

我们采取的典型方法是使用一个与视图紧密耦合且仅包含该信息的viewmodel。InputModels也是如此,它们应该只包含将传入的属性。至于继承部分,我将远离这种方法。只需创建简单、扁平的DTO,并从您的域模型映射它们。应该没有逻辑,所以DRY并不真正适用于应用程序的这一层。

根据第一个答案,我们还没有看到viewmodel将如何在页面上使用。正如他所说,viewmodel应该只包含满足显示视图要求的数据。您不应该只是盲目地将域模型中的每个字段复制到viewmodel中

我也不喜欢视图模型中有HASRERROR标志。使用数据批注或从IValidateableObject继承来对您的帖子执行验证

我也不认为您需要像在viewmodel中一样注入值。如果您应该能够从linq查询或webservice请求直接projet到viewmodel中


最后一点是,对于页面上的下拉列表,只返回您需要在字典或某个小类中的Id和描述的数据,这样您就不会返回所有数据。

这里有点不清楚您在处理什么。模型是一个很有意思的术语,对各种各样的人来说,它可以意味着各种各样的事情

如果类、费用、发票等是实体,也就是说它们直接与数据库表相关,那么为了视图的目的对它们进行子类化,就像开发人员所做的那样,是100%错误的。然而,如果它们也仅仅是视图模型,那么对它们进行子类化可能有好处,也可能没有好处

如果它们是实体,那么您的开发人员是正确的,因为您不应该向视图传递整个实体。但是,在本例中,解决方案是创建仅包含视图所需属性的视图模型。然后将实体中的数据映射到/映射到这些视图模型


关于使用AutoMapper进行映射的次要问题:您确实不应该使用AutoMapper来映射到实体。图书馆的开发者自己也说过同样的话。AutoMapper从未打算用于将数据映射回实体,如果这样做,您将遇到实体框架的各种特殊问题。这些都是可以解决的,在我了解更多之前,我已经亲自做过很多次了,但是您开始需要的代码量和您必须要做的自定义事情开始否定使用AutoMapper的所有好处。我建议您只需手动将视图模型中的数据映射回实体。

您的新开发人员的风格取决于本例中的技术实体框架-在MHO中,实体框架并不总是适用于正确的设计

我的方法是

模型 应使用接口进行逻辑设计-不知道如何使用接口 但将满足未来的需求。 遗产应该尽可能地保持浅而不破坏一个好的遗产 模型设计

视图应仅通过控制器与BS交互。 数据服务应该只与业务服务交互。 每个演示文稿都应具有自己的ViewModel,该ViewModel应尽可能平坦。 但是,ViewModel可能有子ViewModels

我在数据库服务层中使用DAPPER for,并创建了一个代码生成器,它将 生成DS方法和存储的进程。DS方法将只具有相关的 要在数据库中插入/更新字段的属性。 这使您的代码精简、快速且易于管理
当你离开团队,其他人必须接管时。

好的,我们通常只有一个视图模型,所以输入模型的概念有点新。我们是否应该有一个视图模型,它被提交,然后通过一个自动映射器转换成一个输入模型,然后传递回服务层?视图模型是为呈现页面时创建的,InputModel用于绑定操作中的输入。拥有独立的模型可以让您精心设计一个DTO,这正是您在这种情况下所需要的。ViewModel通常不止一个InputModel,因为它具有用于显示的字符串值和用于下拉列表的项目等。