从 dto 映射到实体时,实体 ctor 的参数应该是什么?

问题描述 投票:0回答:1

领域驱动设计聚合根Demo实体:

public class Demo : FullCompanyEntity<int>, IAggregateRoot
{
    public string? FirstName { get; private set; }
    public string LastName { get; private set; }
    public string? FullName { get; private set; }
    public string? Phone { get; private set; }
    public string? Email { get; private set; }
    public int? LeadId { get; private set; }
    public int? SaleId { get; private set; }
    public DateTime StartedAt { get; private init; }
    public DateTime? EndedAt { get; private set; }
    public int? TotalSpentTime { get; private set; }
    public double Latitude { get; private set; } // float8 psg type
    public double Longitude { get; private set; }// float8 psg type
    public Address? Address { get; private set; }
    public bool IsLive { get; private set; }


    private Demo() { } // for ef

    public Demo(double latitude,
                double longitude,
                string lastName,
                in int companyId,
                in int importerId,
                in int organisationId,
                in int distributorId,
                Address? address = null,
                string? firstName = null,
                string? phone = null,
                string? email = null,
                int? leadId = null) : base(companyId, importerId, organisationId, distributorId)
    {

        Guard.Against.LatitudeFormat(latitude);
        Guard.Against.LongitudeFormat(longitude);

        Latitude = latitude;
        Longitude = longitude;
        Address = address;
        FirstName = firstName;
        LastName = lastName;
        FullName = firstName.FullName(lastName);
        Phone = phone;
        Email = email;
        LeadId = leadId;

        StartedAt = DateTime.UtcNow;
        IsLive = true;
    }
}

请求Dto:

public class RequestDemoDto
    {
        public string? FirstName { get; private set; }
        public string LastName { get; private set; }
        public string? Phone { get; private set; }
        public string? Email { get; private set; }
        public int? LeadId { get; private set; }
        public int? SaleId { get; private set; }
        public double Latitude { get; private set; } 
        public double Longitude { get; private set; }
        public AddressDto? Address { get; private set; }
    }
  • 我上面分享了两个类,一个是领域实体,另一个是request dto,它将用于API接收请求。

  • 这里我想到了几个问题。在问他们之前,我想先解释一下实体ctor的目的。

  • 演示实体不得在没有必需属性的情况下初始化(必需的属性纬度、经度、姓氏、公司 ID、导入者 ID、组织 ID、分销商 ID)

  • 即使演示实体不需要某些属性,用户(通过 dto 请求 Web API 的用户)也可以在第一次初始化时设置它们 等等。名字、电话、电子邮件、leadId

  • 但是,我创建了这样一个ctor,以便在上面的ctor中提供我想要的功能,但这里出现了类似的问题。

当从 dto 映射到 demo 或简单地将参数传递给 ctor 时,如下所示;

var demo = new Demo(demoDto.Latitude, demoDto.Longitude, demoDto.LastName, companyId, importerId, organisationId, distributorId, firstName: demoDto.FirstName, phone: demoDto.Phone, email: demoDto.Email, leadId: demoDto.LeadId);

数据出现一些问题。例如,如果phone或firstname是空字符串,那么它们在数据库中不会被记录为null。 或者如果leadId默认为0,则数据库leadid将为0而不是null。但我希望它为空。但如上所示,用户设置的内容仍然 由于运行时不知道它的作用,因此我需要在从 dto 映射实体时将所有 dto 属性切换到 ctor。

这种情况我该怎么办,我应该设计什么样的ctor或者dto的实体映射应该是什么样的?

注意: 如果数据库中未设置任何值,则名字、电话、电子邮件、LeadId、SaleId、Address 必须为空。

注意: 在数据库中保留 null 是一个不好的方法吗?您也可以评论这个问题。

感谢任何能帮忙或不能帮忙的人。

c# asp.net-core .net-core constructor domain-driven-design
1个回答
0
投票

您可以创建一个仅包含所需值的构造函数

public Demo(double latitude,
            double longitude,
            string lastName,
            in int companyId,
            in int importerId,
            in int organisationId,
            in int distributorId) : base(companyId, importerId, organisationId, distributorId)
{

    Guard.Against.LatitudeFormat(latitude);
    Guard.Against.LongitudeFormat(longitude);

    Latitude = latitude;
    Longitude = longitude;
    LastName = lastName;

    StartedAt = DateTime.UtcNow;
    IsLive = true;
}

更改非必需属性以允许公共设置

public string? FirstName { get; set; }
public string? Phone { get; set; }
public string? Email { get; set; }
public int? LeadId { get; set; }
public Address? Address { get; set; }

然后你可以做如下的事情

var demo = new Demo(demoDto.Latitude, demoDto.Longitude, demoDto.LastName, companyId, importerId, organisationId, distributorId)
{
    FirstName = !string.IsNuulOrEmpty(demoDto.FirstName) ? demoDto.FirstName : null,
    Phone = !string.IsNuulOrEmpty(demoDto.Phone) ? demoDto.Phone : null,
    Email =  !string.IsNuulOrEmpty(demoDto.Email) ? demoDto.Email : null,
    LeadId = demoDto.LeadID > 0 ? demoDto.LeadID : null
};

您可能还想执行以下操作:

private string? _firstName;
public string? FirstName
{
    get
    {
        return _firstName;
    }
    set
    {
        _firstName = value;
        if (!string.IsNullOrEmpty(_firstName))
        {
            FullName = _firstName.FullName(LastName);
        }
    }
}

您似乎没有对 Address 做任何事情 - 看起来您需要使 dto 适应 Address 类型或在设置它时适当地构造它,但这应该遵循类似的模式。

© www.soinside.com 2019 - 2024. All rights reserved.