实体框架核心2.1拥有的类型和嵌套的值对象



我正在学习DDD,我目前正在学习的教程是使用NHibernate实现的,但由于我缺乏相关经验,我决定使用EF Core 2.1完成课程。

然而,我目前有点拘泥于以下内容:我有三个类Customer,它是一个实体和两个值对象(CustomerStatus和它内部的值对象ExpirationDate(,如下所示:

public class Customer : Entity
{
//... constructor, other properties and behavior omitted for the sake of simplicity
public CustomerStatus Status { get; set; }
}
public class CustomerStatus : ValueObject<CustomerStatus>
{
// customer status is enum containing two values (Regular,Advanced)
public CustomerStatusType Type { get; }
public ExpirationDate ExpirationDate { get; }
}
public class ExpirationDate : ValueObject<ExpirationDate>
{
//... constructor, other properties and behavior omitted for the sake of simplicity
public DateTime? Date { get; private set; }
}

当我尝试在DbContext内部执行以下操作时:

modelBuilder.Entity<Customer>(table =>
{      
table.OwnsOne(x => x.Status,
name =>
{
name.Property(x => x.ExpirationDate.Date).HasColumnName("StatusExpirationDate");
name.Property(x => x.Type).HasColumnName("Status");
});
});

我得到以下错误:

表达式"x=>x.ExpirationDate.Date"不是有效的属性表达式。表达式应表示简单的属性访问:"t=>t.MyProperty"。
参数名称:propertyAccessExpression"">

除此之外,我还尝试过做一些事情,比如:

table.OwnsOne(x => x.Status.ExpirationDate,
name =>
{
name.Property(x => x.Date).HasColumnName("StatusExpirationDate");
});
table.OwnsOne(x => x.Status,
name =>
{
name.Property(x => x.Type).HasColumnName("Status");
});

但它也导致:

表达式"x=>x.Status.ExpirationDate"不是有效的属性表达式。表达式应表示简单的属性访问:"t=>t.MyProperty".

我也尝试过:

modelBuilder.Entity<Customer>()
.OwnsOne(p => p.Status, 
cb => cb.OwnsOne(c => c.ExpirationDate));

但是运气也不好。。。无论如何,任何帮助都将不胜感激,如果可能的话,如果有人能解释为什么我的尝试都不起作用,那将是一件非常好的事情?提前感谢!

更新

在做了Ivan的评论中所说的第一件事之后,我得到了关于CustomerStatus类构造函数的错误,所以我添加了默认的受保护的构造函数。

在那之后,我开始得到错误:

实体类型"CustomerStatus"的字段"k_BackingField"是只读的,因此无法设置。

如果有帮助的话,这是我的CustomerStatus类的内部:

public class CustomerStatus : ValueObject<CustomerStatus>
{
public CustomerStatusType Type { get; }
public ExpirationDate ExpirationDate { get; }
public static readonly CustomerStatus Regular =
new CustomerStatus(CustomerStatusType.Regular, ExpirationDate.Infinite);
public bool IsAdvanced => Type == CustomerStatusType.Advanced && !ExpirationDate.IsExpired;
private CustomerStatus(CustomerStatusType type, ExpirationDate expirationDate)
{
Type = type;
ExpirationDate = expirationDate;
}
protected CustomerStatus()
{
}
public static CustomerStatus Create(CustomerStatusType type, ExpirationDate expirationDate)
{
return new CustomerStatus(type, expirationDate);
}
public CustomerStatus Promote()
{
return new CustomerStatus(CustomerStatusType.Advanced, ExpirationDate.Create(DateTime.UtcNow.AddYears(1)).Value);
}
protected override bool EqualsCore(CustomerStatus other)
{
return Type == other.Type && ExpirationDate == other.ExpirationDate;
}
protected override int GetHashCodeCore()
{
return Type.GetHashCode() ^ ExpirationDate.GetHashCode();
}
}

更新

它只需要在CustomerStatus类中的TypeExpirationDate属性上添加private setter,结合Ivan的回答,它就像一个魅力。非常感谢!

您的尝试不起作用,因为拥有的类型只能通过其所有者实体进行配置,更具体地说,可以通过OwnsOne方法返回的自己的生成器进行配置,或者作为所有者实体生成器的OwnsOne方法的Action<T>参数的参数提供。

所以配置应该是这样的(注意嵌套的OwnsOne(:

modelBuilder.Entity<Customer>(customer =>
{      
customer.OwnsOne(e => e.Status, status =>
{
status.Property(e => e.Type).HasColumnName("Status");
status.OwnsOne(e => e.ExpirationDate, expirationDate =>
{
expirationDate.Property(e => e.Date).HasColumnName("StatusExpirationDate");
});
});
});

相关内容

  • 没有找到相关文章

最新更新