C#MongoDB:如何正确映射域对象?

hoe*_*etz 26 c# domain-driven-design dto mongodb

我最近开始阅读Evans的Domain-Driven设计书,并开始了一个小样本项目,以获得DDD的一些经验.同时我想了解更多关于MongoDB的知识,并开始用MongoDB和最新的官方C#驱动程序替换我的SQL EF4存储库.现在这个问题是关于MongoDB映射的.我看到用公共getter和setter映射简单对象非常容易 - 没有痛苦.但是我在没有公共设置者的情况下映射域实体有困难.据我所知,构建有效实体的唯一真正干净的方法是将所需的参数传递给构造函数.请考虑以下示例:

public class Transport : IEntity<Transport>
{
    private readonly TransportID transportID;
    private readonly PersonCapacity personCapacity;

    public Transport(TransportID transportID,PersonCapacity personCapacity)
    {
        Validate.NotNull(personCapacity, "personCapacity is required");
        Validate.NotNull(transportID, "transportID is required");

        this.transportID = transportID;
        this.personCapacity = personCapacity;
    }

    public virtual PersonCapacity PersonCapacity
    {
        get { return personCapacity; }
    }

    public virtual TransportID TransportID
    {
        get { return transportID; }
    } 
}


public class TransportID:IValueObject<TransportID>
{
    private readonly string number;

    #region Constr

    public TransportID(string number)
    {
        Validate.NotNull(number);

        this.number = number;
    }

    #endregion

    public string IdString
    {
        get { return number; }
    }
}

 public class PersonCapacity:IValueObject<PersonCapacity>
{
    private readonly int numberOfSeats;

    #region Constr

    public PersonCapacity(int numberOfSeats)
    {
        Validate.NotNull(numberOfSeats);

        this.numberOfSeats = numberOfSeats;
    }

    #endregion

    public int NumberOfSeats
    {
        get { return numberOfSeats; }
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,自动化在这里不起作用.现在我可以手动映射这三个类BsonClassMaps,它们将被存储得很好.问题是,当我想从DB加载它们时我必须将它们加载为BsonDocuments,并将它们解析为我的域对象.我尝试了很多东西,但最终没能得到一个干净的解决方案.我真的必须使用MongoDB的公共getter/setter生成DTO并将它们映射到我的域对象吗?也许有人可以给我一些建议.

Rob*_*tam 15

可以对属性为只读的类进行序列化/反序列化.如果你想保持你的域对象持久性无知,你会不会想用BsonAttributes引导序列,正如你指出的自动映射需要读/写性能,所以你必须注册类映射自己.例如,班级:

public class C {
    private ObjectId id;
    private int x;

    public C(ObjectId id, int x) {
        this.id = id;
        this.x = x;
    }

    public ObjectId Id { get { return id; } }
    public int X { get { return x; } }
}
Run Code Online (Sandbox Code Playgroud)

可以使用以下初始化代码进行映射:

BsonClassMap.RegisterClassMap<C>(cm => {
    cm.MapIdField("id");
    cm.MapField("x");
});
Run Code Online (Sandbox Code Playgroud)

请注意,私有字段不能只读.另请注意,反序列化会绕过构造函数并直接初始化私有字段(.NET序列化也以这种方式工作).

这是一个测试这个的完整示例程序:

http://www.pastie.org/1822994

  • 小点:删除readonly字段使其等同于`public ObjectId Id {get; 私人集; }`auto-property和字段可以完全删除. (2认同)
  • 虽然这是一个可能的解决方案,**它仍然会影响您的模型**,在您提供的具体示例中,要求字段不是“只读”。每个团队都必须自己决定这对于他们的项目是否可以接受。 (2认同)