简体   繁体   English

DDD实体框架值类型

[英]DDD Entity Framework Value Type

I'm struggling with using EF6 with DDD principles, namely value objects attached to aggregates. 我正在努力使用具有DDD原理的EF6,即附加到集合的值对象。 I can't seem to get migrations to generate that reflect the model and I feel like I'm fighting the tooling instead of actually being productive. 我似乎无法生成能够反映模型的移植,而且我觉得自己正在与工具作战,而不是实际发挥作用。 Given that a NoSQL implementation is probably more appropriate, this is what I'm stuck with. 鉴于NoSQL实现可能更合适,这就是我要坚持的。

The first thing that I ran into was the lack of support for interface properties on an EF entity. 我遇到的第一件事是缺少对EF实体上的接口属性的支持。 The work around for that was to add concrete properties to the entity for each of the implementations, but not to the interface. 解决该问题的方法是为每个实现的实体添加具体属性,但不向接口添加具体属性。 When I implemented the interface, I added logic to return the right one. 当实现接口时,我添加了逻辑以返回正确的接口。 I had to do this in order to get any migrations to create the properties for the Policies. 我必须这样做才能进行所有迁移,以创建策略的属性。 See Fund.LargestBalanceFirstAllocationPolicy and Fund.PercentageBasedAllocationPolicy This was annoyance one. 请参阅Fund.LargestBalanceFirstAllocationPolicy和Fund.PercentageBasedAllocationPolicy。

The current annoyance and the genesis of the question is the PercentageBasedAllocationPolicy.AllocationValues property. 当前的困扰和问题的根源是PercentageBasedAllocationPolicy.AllocationValues属性。 No matter what I do, when running add-migration, I don't get any tables or fields to represent the AllocationValues. 无论我做什么,在运行添加迁移时,我都不会得到任何表或字段来表示AllocationValues。 This is basically a collection of DDD value objects hanging off of another value object, which hangs off of an aggregate. 这基本上是DDD值对象的集合,这些DDD值对象挂在另一个值对象上,而另一个值对象挂在一个聚合上。

I'm convinced that the model and code are correct to do what I want, but EF keeps getting in the way. 我坚信模型和代码可以正确执行我想要的操作,但是EF一直在妨碍您。 In MongoDB, when dealing with an interface property, it actually stores the object type in a string so that it knows how to rehydrate the object. 在MongoDB中,当处理接口属性时,它实际上将对象类型存储在字符串中,以便它知道如何为对象补水。 I'm considering serializing the problem areas here to a blob and storing it on the object now, which is just as evil... 我正在考虑将这里的问题区域序列化为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; }
}

A value type (in EF marked as ComplexType) will never have any tables. 值类型(在EF中标记为ComplexType)永远不会有任何表。 The reason being is that a value types are (by definition) really just values. 原因是(根据定义)值类型实际上只是值。 They don't have any Id( otherwise they would be enities) thus you can't create a table for them. 它们没有任何ID(否则它们将是实体),因此您无法为它们创建表。

also if i review the requirements for complex type in entity framework https://msdn.microsoft.com/en-us/library/bb738472(v=vs.100).aspx i notice that you can't use inheritance on complex types. 另外,如果我在实体框架https://msdn.microsoft.com/zh-cn/library/bb738472(v=vs.100).aspx中查看了复杂类型的要求,我也会注意到您不能对复杂类型使用继承。 Thus if you want to use complex type in your entity framework as you've shown here then you need to make your property a PercentageBasedAllocationPolicy instead of an IAllocationPolicy. 因此,如果您想要在实体框架中使用复杂的类型(如此处所示),则需要将属性设置为PercentageBasedAllocationPolicy而不是IAllocationPolicy。

Alternatively you could turn it into an entity with automatic generated keys. 或者,您可以将其变成具有自动生成的键的实体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM