具有值对象的实体框架核心

时间:2018-03-02 07:38:14

标签: c# domain-driven-design entity-framework-core aggregates

我正在通过将聚合和值对象与EF7结合使用来解决问题。

这是聚合:

public class MasterAgreement
{
    private string _name;

    public Guid Key { get; set; }
    public MasterAgreementRaise RegularRaise { get; private set; }
    public MasterAgreementRaise MarketRaise { get; private set; }

    protected MasterAgreement()
    { }

    public MasterAgreement(Guid key)
    {
        Key = key;
    }

    public MasterAgreement(Guid key, string name, MasterAgreementRaise regularRaise, MasterAgreementRaise marketRaise)
    {
        Key = key;
        _name = name;
        RegularRaise = regularRaise ?? throw new DomainException("Regular raise is missing");
        MarketRaise = marketRaise ?? throw new DomainException("Market raise is missing");
    }

    public void Update(MasterAgreement masterAgreement)
    {
        _name = masterAgreement._name;
        RegularRaise = masterAgreement.RegularRaise;
        MarketRaise = masterAgreement.MarketRaise;
    }
   }

这是价值对象:

public class MasterAgreementRaise : ValueObject
{
    public int RaiseType { get; private set; }
    public int ConditionType { get; private set; }
    public decimal? Value { get; private set; }

    private MasterAgreementRaise() { }

    public MasterAgreementRaise(int raiseType, int conditionType, decimal? value)
    {
        RaiseType = raiseType;
        ConditionType = conditionType;
        Value = value;
    }

    protected override IEnumerable<object> GetAtomicValues()
    {
        // Using a yield return statement to return each element one at a time
        yield return RaiseType;
        yield return ConditionType;
        yield return Value;
    }
}

因此MasterAgreement包含2个公共MasterAgreementRaise字段

用于生成数据库的实体配置以这种方式完成,并正确生成数据库符合DDD原则:

public class MasterAgreementTypeConfiguration : IEntityTypeConfiguration<MasterAgreement>
{
    public void Configure(EntityTypeBuilder<MasterAgreement> builder)
    {
        builder.HasKey(item => item.Key);

        builder.Property<Guid>("Key");
        builder.Property<string>("Name").IsRequired().HasMaxLength(250);

        builder.OwnsOne(item => item.RegularRaise);
        builder.OwnsOne(item => item.MarketRaise);
    }
}

当尝试从数据库更新或删除主协议时,EF7无法处理此

更新期间的错误是: 无法跟踪实体类型“MasterAgreement.RegularRaise#MasterAgreementRaise”的实例,因为已经跟踪了另一个具有{'MasterAgreementKey'}相同键值的实例。替换所拥有的实体时,修改属性而不更改实例或首先分离先前拥有的实体条目。

在删除过程中: 'MasterAgreement'的实体正在与MasterAgreement.RegularRaise#MasterAgreementRaise'共享表'MasterAgreement',但是没有这种类型的实体具有被标记为'已删除'的相同键值

如何通过添加标识符来解决这个问题而不会丢失值对象并将它们更改为实体?

所有帮助将不胜感激

1 个答案:

答案 0 :(得分:0)

现在不支持此DDD值对象方案,它将是EF Core 2.1版的地址。

您可以按照此处same issue

在此处使用更好的expcetion消息和版本2.1的最终解决方案来解决issue