C#MongoDB:如何正确映射域对象? [英] C# MongoDB: How to correctly map a domain object?

查看:492
本文介绍了C#MongoDB:如何正确映射域对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I recently started reading Evans' Domain-Driven design book and started a small sample project to get some experience in DDD. At the same time I wanted to learn more about MongoDB and started to replace my SQL EF4 repositories with MongoDB and the latest official C# driver. Now this question is about MongoDB mapping. I see that it is pretty easy to map simple objects with public getters and setters - no pain there. But I have difficulties mapping domain entities without public setters. As I learnt, the only really clean approach to construct a valid entity is to pass the required parameters into the constructor. Consider the following example:

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生成带有公共获取者/设置者的DTO并将其映射到我的域对象吗?也许有人可以给我一些建议.

Obviously automapping does not work here. Now I can map those three classes by hand via BsonClassMaps and they will be stored just fine. The problem is, when I want to load them from the DB I have to load them as BsonDocuments, and parse them into my domain object. I tried lots of things but ultimately failed to get a clean solution. Do I really have to produce DTOs with public getters/setters for MongoDB and map those over to my domain objects? Maybe someone can give me some advice on this.

推荐答案

可以对属性为只读的类进行序列化/反序列化.如果您试图使域对象的持久性变得无知,那么您将不希望使用BsonAttributes来指导序列化,并且正如您所指出的,AutoMapping需要读/写属性,因此您必须自己注册类映射.例如,类:

It is possible to serialize/deserialize classes where the properties are read-only. If you are trying to keep your domain objects persistance ignorant, you won't want to use BsonAttributes to guide the serialization, and as you pointed out AutoMapping requires read/write properties, so you would have to register the class maps yourself. For example, the class:

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

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

Can be mapped using the following initialization code:

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

请注意,私有字段不能为只读.还要注意,反序列化会绕过您的构造函数,而直接初始化私有字段(.NET序列化也可以这种方式).

Note that the private fields cannot be readonly. Note also that deserialization bypasses your constructor and directly initializes the private fields (.NET serialization works this way also).

这是一个完整的示例程序,可以对此进行测试:

Here's a full sample program that tests this:

http://www.pastie.org/1822994

这篇关于C#MongoDB:如何正确映射域对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆