Search code examples
c#linq-to-entitiessingle-responsibility-principle

Single Responsible Principle and LINQ to Entities


I.e. my have the following model:

public class CompanyDto
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string CompanyLogo { get; set; }
    public string EmailUser { get; set; }
    public int UserCount { get; set; }
}

and some method in some repository class, which selects data from Db and push it to domain DTO class:

public List<CompanyDto> CompanyList()
{
    var list = (from i in _db.Companies
                select new CompanyDto()
                {
                    ID = i.Id,
                    CompanyLogo = i.CompanyLogo,
                    Name = i.Name,
                    UserCount = i.Users.Count,
                    EmailUser = i.UserDetail.Email
                }).ToList();

    return list;
}

as we can see, our BL model requires to get combine data from 3 entities (tables): Company, UserDetail and count of users from Users

It works and works fine. But I think about SRP. This principle says, that should be one and only one reason to change class. But in our case we have 2 reasons to change class:

  1. change structure of DB entities
  2. change DTO class

Does this code violate SRP?


Solution

  • Does this code violate SRP ?

    Yes-ish. But don't worry.

    I believe your question might be better received at Code review.

    IMO you are quite right but what I see is common and would go through all code reviews I am aware of.
    I, presently, see no way of rewriting your code to 2 parts [both with their own SRP] as what you are describing is the mapping between two data carriers. (well, I see one by creating yet an in-betweeen class but that would be superfluous IMO)

    What you could do; is to move the mapping [database entity Company -> DTO CompanyDTO] to another place. This place (here implemented as an extension method) is then responsible for all mappings from database entities to DTOs.

    public static class CompanyExtensions{
        public static CompanyDto ToDto( this Company me ){
            return new CompanyDto{
                ID = me.Id, 
                ...the rest of the fields.
            }
        }
    }
    

    which will be called like so:

    public List<CompanyDto> CompanyList()
    {
        var result = (from company in _db.Companies
            select company.ToDto());
        return result.ToList();
    }
    

    The reason to use an extension method instead of a method in CompanyDto is that you don't want the database entities to leak out of your DAL.
    The reason to use an extension method instead of a helper class is that you get intellisense.