将sql查询结果映射到域模型

时间:2014-12-22 19:00:14

标签: c# domain-driven-design repository-pattern

我有以下域名模型:

public class Company
{
    public int Id { get; private set; }
    public string Name { get; private set; } 
    public BlaBla BlaBla { get; private set; }
    ...
    ...

    public void ChangeName(string newName)
    {
        //business logic here

        Name = newName;
    }    
}

我们已经使用Entity Framework实现了存储库模式,它们都运行良好。 对于一个非常特殊的情况(使用遗留数据库),我们需要跳过EF并使用普通的sql查询并自己进行映射。

对于映射,代码(伪代码)如下:

using connection
    using command
        company = new Company();
        while (reader.read())
            company.ChangeName(reader["company_name"]);
        end while
     end using
 end using

正如您所看到的那样,公司的所有属性都是“私有集”,因为我们正在练习域驱动设计,因此我们无法编写company.Id = reader [“Id”]并且我们必须使用域方法来“填充“公司对象的属性。

有没有一种优雅的方式来做这件事,比如EF?如何在不创建方法SetId(int id)?

的情况下设置Id属性

2 个答案:

答案 0 :(得分:0)

您可以使用PropertyInfo(如下所示):

foreach (PropertyInfo propInfo in theType.GetProperties())
{
    for (int i = 0; i < reader.FieldCount; i++)
    {
        if (reader.GetName(i).Trim().ToLower() == propInfo.Name.Trim().ToLower())
        {
            object asObj = reader.GetValue(i);
            if (asObj is System.DBNull) propInfo.SetValue(thisRow, null, null);
            else propInfo.SetValue(thisRow, reader.GetValue(i), null);
        }
    }
}

类型将是您要将属性映射到的typeof(YourType)

答案 1 :(得分:0)

在DDD环境中,创建不是构造函数的任务。每个构造函数都应该被私有或保护以满足DDD。有时,当EF(或其他工具)位于中间时,您必须提供可见的默认构造函数。

如上所述,构造不是构造函数的任务,而是可以使用工厂,甚至更好的builder(后者为您提供更具弹性的对象创建)。比一个更优雅的解决方案可能是:

将SQL查询输出映射到DTO。

public class CompanyDTO
{
    public int Id { get; set; }
    public string Name { get; set; } 
    public BlaBla BlaBla { get; set; }
    // no trace of business logic here
}

并且在您的检索逻辑中,而不是构建真正的Company对象,而不是创建相关的DTO并使用其成员作为构建器的参数:

//REPO PSEUDO CODE
using connection
    using command
        companyDTO = new CompanyDTO();
        while (reader.read())
            companyDTO.Name = reader["company_name"];
        end while
    end using
end using

// build your real `Company` object using as parameters the one 
// stored in the realted DTO.

company = CompanyBuilder.NewBuilder()
                        .WithCustomId(companyDTO.id)
                        .WithRegistryInfo(companyDTO.info1, companyDTO.info2, ....)
                        .WithOwnerInfo(companyDTO.owner1, ....)
                        .Build();

return company;

根据您的构造逻辑,您可以考虑摆脱DTO并直​​接调用构建的可能性。我希望我能正确理解问题。

相关问题