0

集約ルートと子エンティティを持つドメイン駆動設計を使用しています。

集約不変条件は、集約ルートConfigurableServiceメソッドを介して強制され、子エンティティのメソッドに連鎖し、グループ間の要件をマップするリストGroupsを使用します。Dependencies

不変の例の 1 つConfigurableServiceは、SkuId がリスト内のいずれかのグループに含まれている場合にのみ、依存関係を作成できるようにすることです。

私が行ってグループまたは依存関係を公開すると(mongodbが永続性を必要とするため)、このドメインロジックをバイパスできます-したがって、以下のようなエンティティメソッドを呼び出すパブリックプロパティでクラスを展開できると考えましたDependenciesおよびGroupsプロパティ:

public class ConfigurableService
{
    List<Groups> groups = new List<Groups>();
    Dependencies dependencies = new Dependencies();

    public void AddDependency(SkuId on, SkuId requires)
    {
        if(IsContainsSku(on) && IsContainsSku(requires))
            this.dependencies.SetRequiresFor(on, requires);
        else
            throw new Exception("SkuId doesnt exist");
    }

    public bool IsContainsSku(SkuId sku)
    {
        foreach(var group in groups)
        {
            if(group.ContainsSku(sku)==true)
            {
                return true;
            }
        }

        return false;
    }

    // other code snipped for breverity

    IEnumerable<Dependency> Dependencies
    {
        get { return this.dependencies.GetAllDependencies(); }

        set
        {
            foreach(var dependency in value)
            {
                this.AddDependency(
                    new SkuId(dependency.Source),
                    new SkuId(dependency.Target)
                    );
            }
        }
    }

    IEnumerable<Group> Groups
    {
        get { return this.groups; }

        set
        {
            this.groups.Clear();

            foreach(var group in groups)
            {
                this.groups.Add(group);
            }
        }
    }
}

これはドメイン ロジックをチェックするため、永続化する必要がある内部プロパティごとに繰り返します。

これは、プロパティが正しい順序で設定されている限り、オブジェクトがビルドされたときにリポジトリから読み取るときに正常に機能します...たとえばDependencies、例外をスローする前にグループが設定された場合 (SkuID は存在しません)。

質問

  1. 不変条件を保護し、Mongodb がドメイン エンティティ オブジェクトを永続化/取得できるようにするための推奨される方法は何ですか?

  2. mongodb がデータベースからハイドレートするときにプロパティが設定される順序を制御できますか?

  3. または、カスタムのシリアル化メソッドを作成するのが最善でしょうか (どうすればよいですか)?

4

1 に答える 1

0

私の同僚は、問題を解決するカスタム シリアライザーを思い付きました。エンティティは、BsonSerializer DTO から手動で再構築できます。

public class ConfigurableServicePersistenceMapper
{
    public ConfigurableServiceId Id { get; set; }
    public string Description { get; set; }
    public HashSet<Group> Groups { get; set; }
    public Dependencies Dependencies { get; set; }
}

public class ConfigurableServiceSerializer : BsonBaseSerializer
{
    public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options)
    {
        // implement using bsonWriter
        if (nominalType != typeof(ConfigurableService))
            throw new Exception("Object should be of type 'ConfigurableService'");

        var obj = (ConfigurableService)value;

        var map = new ConfigurableServicePersistenceMapper()
        {
            Dependencies = obj.Dependencies,
            Description = obj.Description,
            Groups = obj.Groups,
            Id = obj.Id
        };

        BsonSerializer.Serialize(bsonWriter, map);
    }

    public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options)
    {
        // implement using bsonreader
        if (nominalType != typeof(ConfigurableService))
            throw new Exception("object should be of type 'ConfigurableService'");

        var bson = BsonSerializer.Deserialize<BsonDocument>(bsonReader);
        var configurableServiceMapper = BsonSerializer.Deserialize<ConfigurableServicePersistenceMapper>(bson);

        var configurableService = new ConfigurableService(configurableServiceMapper.Id)
        {
            Description = configurableServiceMapper.Description
        };


        foreach (var group in configurableServiceMapper.Groups)
        {
            configurableService.NewGroup(group.Id);
            var retrievedGroup = configurableService.GetGroup(group.Id);

            retrievedGroup.Description = group.Description;

            foreach (var sku in group.Skus)
            {
                retrievedGroup.Add(sku);
            }

            // set requirements
            List<Group> groupList = new List<Group>(configurableServiceMapper.Groups);

            foreach (var sku in group.Skus)
            {
                List<string> dependencies =
                    new List<string>(configurableServiceMapper.Dependencies.GetDependenciesFor(sku));


                foreach (var dependencySkuString in dependencies)
                {
                    retrievedGroup.SetRequirementFor(sku)
                        .Requires(new SkuId(dependencySkuString));
                }
            }
        }
        return configurableService;
    }
}
于 2014-07-22T18:28:33.217 に答える