0

In the following example shows a query to get an employ details. It has a int parameter Id. And there is a DTO class EmployeeDto which also has a field Id with type of string.

https://github.com/JasonGT/NorthwindTraders/blob/master/Src/Application/Employees/Queries/GetEmployeeDetail/GetEmployeeDetailQuery.cs

I will need to create a value-object class EmployeeId which contains some business logic for the employee Id. The Id of the entity class Employee will be changed to type of EmployeeId instead of string.

  1. Should the type of Id of the DTO/Vm class EmployeeDto be string? And Automapper is used to map the string to EmployeeId? So it will be easier for UI to renter the list.
  2. Should the type of the property Id of the query GetEmployeeDetailQuery be primary type string/int? Where to check if the parameter is a valid employee ID (the value object EmployeeId has the validation logic)?

code:

public class GetEmployeeDetailQuery : IRequest<EmployeeDetailVm>
{
    public int Id { get; set; } // Stay as primary type string/int?
    // public EmployeeId Id { get; set; } // or EmployeeId?

    public class GetEmployeeDetailQueryHandler : IRequestHandler<GetEmployeeDetailQuery, EmployeeDetailVm>
    {
        private readonly INorthwindDbContext _context;
        private readonly IMapper _mapper;

        public GetEmployeeDetailQueryHandler(INorthwindDbContext context, IMapper mapper)
        {
            _context = context;
            _mapper = mapper;
        }

        public async Task<EmployeeDetailVm> Handle(GetEmployeeDetailQuery request, CancellationToken cancellationToken)
        {
           var vm = await _context.Employees
                .Where(e => e.EmployeeId == request.Id)
                .ProjectTo<EmployeeDetailVm>(_mapper.ConfigurationProvider) // to be mapped to entity here
                .SingleOrDefaultAsync(cancellationToken);

            return vm;
        }
    }
}

https://github.com/JasonGT/NorthwindTraders/blob/master/Src/Application/Employees/Queries/GetEmployeeDetail/GetEmployeeDetailQuery.cs

namespace Northwind.Application.Employees.Queries.GetEmployeeDetail
{
    public class EmployeeDetailVm : IMapFrom<Employee>
    {
        public int Id { get; set; } // int/string
        // public EmployeeId Id { get; set; } // or EmployeeId?

        public string Title { get; set; }
ca9163d9
  • 27,283
  • 64
  • 210
  • 413

1 Answers1

1

A value object is a domain concept and, as such, should be used where other domain concepts are used.

If data goes over-the-wire I tend to use primitives or, if necessary, other data transfer objects. These DTOs never have any behaviour and when I do want to add some method I tend to use an extension method.

Value objects, as is the case with aggregates/entities, would in all probability be encapsulated to such a degree that they would probably not be suitable for serialization.

Eben Roux
  • 12,983
  • 2
  • 27
  • 48