C# MongoDB : How to correctly map a domain object?

标签 c# mongodb domain-driven-design dto

我最近开始阅读 Evans 的领域驱动设计书,并开始了一个小型示例项目,以获取一些 DDD 经验。同时,我想了解更多关于 MongoDB 的信息,并开始用 MongoDB 和最新的官方 C# 驱动程序替换我的 SQL EF4 存储库。 现在这个问题是关于 MongoDB 映射的。我看到使用公共(public) getter 和 setter 映射简单对象非常容易——那里没有痛苦。但是我很难在没有公共(public) 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; }
    }
}

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

最佳答案

可以序列化/反序列化属性为只读的类。如果您试图让您的域对象持久性无知,您将不想使用 BsonAttributes 来指导序列化,并且正如您指出的那样 AutoMapping 需要读/写属性,因此您必须自己注册类映射。比如类:

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; } }
}

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

BsonClassMap.RegisterClassMap<C>(cm => {
    cm.MapIdField("id");
    cm.MapField("x");
});

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

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

http://www.pastie.org/1822994

关于C# MongoDB : How to correctly map a domain object?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5744430/

相关文章:

c# - Linq:创建表达式的逻辑逆

java - MongoDB Java 驱动程序 : MongoCore Driver vs. MongoDB 驱动程序与 MongoDB 异步驱动程序

mongodb - MongoDB 中基于游标的分页,对 2 个属性进行排序

delphi - Delphi 是否有任何框架/库接近 Bold/Eco 提供的功能?

javascript - 获取通过 Office/Graph API 设置的 Outlook 加载项 (js) 中的 SingleValueExtendedProperties?

c# - 公共(public)静态方法+接口(interface)

node.js - 我应该转向基于微服务的架构吗?

asp.net-mvc-3 - MVC DDD 并为业务逻辑抛出错误

c# - 从 JavaScript 数组创建接口(interface)类型列表

node.js - 使用 $group 时是否可以列出不存在的组?