DDD实体框架值类型

时间:2016-05-02 18:34:54

标签: entity-framework entity-framework-6 domain-driven-design

我正在努力将EF6与DDD原则一起使用,即附加到聚合的值对象。我似乎无法通过生成来反映模型的迁移,我觉得我正在与工具作斗争,而不是真正有效率。鉴于NoSQL实现可能更合适,这就是我所坚持的。

我遇到的第一件事是缺乏对EF实体的接口属性的支持。解决这个问题的方法是为每个实现添加具体属性,但不为接口添加。当我实现界面时,我添加了逻辑以返回正确的界面。我必须执行此操作才能进行任何迁移以创建策略的属性。见Fund.LargestBalanceFirstAllocationPolicy和Fund.PercentageBasedAllocationPolicy这是烦恼之一。

当前的烦恼和问题的起源是PercentageBasedAllocationPolicy.AllocationValues属性。无论我做什么,在运行add-migration时,我都没有得到任何表或字段来表示AllocationValues。这基本上是一个DDD值对象的集合,它挂在另一个值对象之外,它挂起了聚合。

我确信模型和代码是正确的,可以做我想要的,但EF一直在阻碍。在MongoDB中,当处理接口属性时,它实际上将对象类型存储在字符串中,以便它知道如何对对象进行再水化。我正在考虑将问题区域序列化为blob并将其存储在对象上,这同样是邪恶的......

public interface IFund
{
    Guid Id {get;}
    string ProperName {get;}
    IAllocationPolicy AllocationPolicy{get;}
    void ChangeAllocationPolicy(IAllocationPolicy newAllocationPolicy)
}


public class Fund : IFund
{
    public Fund()
    {

    }

    public Fund(Guid id, string nickName, string properName)
    {
        Id = id;
        Nickname = nickName;
        ProperName = properName;

        // This is stupid too, but you have to instantiate these objects inorder to save or you get some EF errors.  Make sure the properties on these objects are all defaulted to null.
        LargestBalanceFirstAllocationPolicy = new LargestBalanceFirstAllocationPolicy();
        PercentageBasedAllocationPolicy = new PercentageBasedAllocationPolicy();

    }

    public Guid Id { get; private set; }

    public string ProperName { get; private set; }


    // Do not add this to the interface.  It's here for EF reasons only.  Do not use internally either.  Use the interface implemention of AllocationPolicy instead
    public LargestBalanceFirstAllocationPolicy LargestBalanceFirstAllocationPolicy
    {
        get; private set;
    }

    // Do not add this to the interface.  It's here for EF reasons only.  Do not use internally either.  Use the interface implemention of AllocationPolicy instead
    public PercentageBasedAllocationPolicy PercentageBasedAllocationPolicy
    {
        get; private set;
    }


    public void ChangeAllocationPolicy(IAllocationPolicy newAllocationPolicy)
    {
        if (newAllocationPolicy == null) throw new DomainException("Allocation policy is required");

        var allocationPolicy = newAllocationPolicy as PercentageBasedAllocationPolicy;
        if (allocationPolicy != null) PercentageBasedAllocationPolicy = allocationPolicy;

        var policy = newAllocationPolicy as LargestBalanceFirstAllocationPolicy;
        if (policy != null  ) LargestBalanceFirstAllocationPolicy = policy;
    }

    public IAllocationPolicy AllocationPolicy
    {
        get {

            if (LargestBalanceFirstAllocationPolicy != null)
                return LargestBalanceFirstAllocationPolicy;

            if (PercentageBasedAllocationPolicy != null)
                return PercentageBasedAllocationPolicy;

            return null;
        }

    }
}

public interface IAllocationPolicy
{
    T Accept<T>(IAllocationPolicyVisitor<T> allocationPolicyVisitor);
}

public class LargestBalanceFirstAllocationPolicy : IAllocationPolicy
{
    public T Accept<T>(IAllocationPolicyVisitor<T> allocationPolicyVisitor)
    {
        return allocationPolicyVisitor.Visit(this);
    }
}

[ComplexType]
public class PercentageBasedAllocationPolicy : IAllocationPolicy
{
    public PercentageBasedAllocationPolicy()
    {
        AllocationValues = new List<PercentageAllocationPolicyInfo>();
    }

    public List<PercentageAllocationPolicyInfo> AllocationValues { get; private set; }

    public T Accept<T>(IAllocationPolicyVisitor<T> allocationPolicyVisitor)
    {
        return allocationPolicyVisitor.Visit(this);
    }
}

[ComplexType]
public class PercentageAllocationPolicyInfo
{
    public Guid AssetId { get; private set; }

    public decimal Percentage { get; private set; }
}

1 个答案:

答案 0 :(得分:0)

值类型(在EF中标记为ComplexType)永远不会有任何表。原因是值类型(根据定义)实际上只是值。他们没有任何Id(否则他们会成为enities),因此你无法为他们创建一个表。

如果我在实体框架中查看复杂类型的要求https://msdn.microsoft.com/en-us/library/bb738472(v=vs.100).aspx,我注意到你不能在复杂类型上使用继承。因此,如果您想在实体框架中使用复杂类型(如此处所示),则需要将属性设置为PercentageBasedAllocationPolicy而不是IAllocationPolicy。

或者,您可以将其转换为具有自动生成密钥的实体。