请求DTO映射到域模型

时间:2013-05-01 10:30:32

标签: servicestack

我有以下域模型:

public class DaybookEnquiry : Entity
{
    public DateTime EnquiryDate { get; set; }
    [ForeignKey("EnquiryType")]
    public int DaybookEnquiryTypeId { get; set; }
    public string AccountNumber { get; set; }
    [ForeignKey("User")]
    public int UserId { get; set; }

    #region Navigation Properties

    public virtual User User { get; set; }
    public virtual DaybookEnquiryType EnquiryType { get; set; }
    public virtual ICollection<DaybookQuoteLine> QuoteLines { get; set; }

    #endregion
}

这是在名为DomainModel的项目中。 Entity只是我的域模型继承的基类,它包含Id字段。

然后我在我的解决方案中有其他项目ServiceInterfaceServiceModelServiceInterface包含我的应用程序的所有服务,ServiceModel包含我的DTO和路线等。我正在尝试遵循此处列出的准则:Physical Project Structure

我的EnquiriesService包含使用存储库在我的数据库中创建新查询的方法:

public void Post(CreateEnquiry request)
{
    // Not sure what to do here..
    // _repository.Insert(request);
}

我的CreateEnquiry请求如下:

[Api("POST a single Enquiry for Daybook.")]
[Route("/enquiries", "POST")]
public class CreateEnquiry : IReturnVoid { }

如您所见,CreateEnquiry请求对象为空。我是否需要向其添加属性以匹配我的域模型,然后使用AutoMapper或类似的东西将字段映射到我的域模型并将其传递到我的存储库?

我的存储库上的Insert方法如下所示:

public virtual void Insert(T entity)
{
    DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
    if (dbEntityEntry.State != EntityState.Detached)
    {
        dbEntityEntry.State = EntityState.Added;
    }
    else
    {
        DbSet.Add(entity);
    }

    DbContext.SaveChanges();
}

1 个答案:

答案 0 :(得分:4)

是。您的服务请求,在这种情况下CreateEnquiry需要拥有您需要的所有属性,以便做您想做的任何事情!

我见过两种不同的Create vs Update模型:

  • 使用一个名为SetEnquiry的请求对象,该对象具有可空的id字段。当null并使用POST HTTP谓词时,它会在内部创建一个新对象。当不为null并使用PATCH HTTP谓词时,它会在内部更新对象。如果POST然后id字段需要为null,则可以使用ServiceStack的AbstractValidator<T>实现来添加逻辑,例如;如果PATCH则id字段不能为null 。这有助于确保您的数据始终如一。
  • 创建两个请求对象 - 一个用于Create,另一个用于Update。 Create甚至没有id字段,Update有一个并且需要它。您可以使用上面使用的相同验证技术,除了独立地应用于每个类,因此如果此动词执行此操作,则不需要的条件检查;如果那个动词那样做

您如何映射到数据模型取决于您。您可以使用AutoMapper之类的东西,也可以使用ServiceStack的内置TranslateToPopulateWith方法。我个人采取了一个中间立场:我创建了自己的对象扩展方法,名为MapToMapFrom,分别统称为TranslateToPopulateWith。我为什么这样做?因为我在我自己的命名空间内控制那些扩展,当我需要进行特殊映射时(比如列名不匹配,或者一个对象比另一个更复杂,或者我只是想忽略一个特定的列)对象)我只是用显式类型重载MapToMapFrom,使其具有比泛型方法更高的特异性。

具体回到你的问题。假设您正在使用内置的TranslateTo,您的服务方法可能如下所示:

public void Post(CreateEnquiry request)
{
    _repository.Insert(request.TranslateTo<Enquiry>());
}

还有一件事:我通常在进行创建和更新时返回对象本身。由于字段可以更改(例如,自动计算字段),我希望将对象返回给调用者。这是偏好,并没有真正影响我给你的答案。把它扔出去!