Entity Framework 核心 2.1 - 自有类型和嵌套值对象
Entity Framework Core 2.1 - owned types and nested value objects
我正在学习 DDD,我目前正在学习的教程是使用 NHibernate 实现的,但由于我缺乏使用它的经验,我决定使用 EF Core 2.1 完成本课程。
但是,我目前有点卡在以下内容中:我有三个 classes 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");
});
});
我收到以下错误:
The expression 'x => x.ExpirationDate.Date' is not a valid property expression. The expression should represent a simple property access: 't => t.MyProperty'.
Parameter name: 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");
});
但这也导致:
The expression 'x => x.Status.ExpirationDate' is not a valid property expression. The expression should represent a simple property access: 't => t.MyProperty'.
我也试过:
modelBuilder.Entity<Customer>()
.OwnsOne(p => p.Status,
cb => cb.OwnsOne(c => c.ExpirationDate));
但也没有运气......无论如何,我们将不胜感激任何帮助,如果可能的话,如果有人能解释为什么我的 none 尝试不起作用,那将是非常好的?提前致谢!
更新
首先按照 Ivan 的评论中所述进行操作后,我收到有关 CustomerStatus
class 构造函数的错误,因此我添加了默认保护的构造函数。
之后我开始收到错误:
Field 'k__BackingField' of entity type 'CustomerStatus' is readonly and so cannot be set.
这是我的CustomerStatus
class的内幕,如果有帮助的话:
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
class 内的 Type
和 ExpirationDate
属性上添加私有设置器,并结合 Ivan 的回答,它就像一个魅力。非常感谢!
您的尝试无效,因为拥有的类型 只能 通过它们的 owner 实体进行配置,更具体地说,通过它们自己的构建器由 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");
});
});
});
我正在学习 DDD,我目前正在学习的教程是使用 NHibernate 实现的,但由于我缺乏使用它的经验,我决定使用 EF Core 2.1 完成本课程。
但是,我目前有点卡在以下内容中:我有三个 classes 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");
});
});
我收到以下错误:
The expression 'x => x.ExpirationDate.Date' is not a valid property expression. The expression should represent a simple property access: 't => t.MyProperty'.
Parameter name: 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");
});
但这也导致:
The expression 'x => x.Status.ExpirationDate' is not a valid property expression. The expression should represent a simple property access: 't => t.MyProperty'.
我也试过:
modelBuilder.Entity<Customer>()
.OwnsOne(p => p.Status,
cb => cb.OwnsOne(c => c.ExpirationDate));
但也没有运气......无论如何,我们将不胜感激任何帮助,如果可能的话,如果有人能解释为什么我的 none 尝试不起作用,那将是非常好的?提前致谢!
更新
首先按照 Ivan 的评论中所述进行操作后,我收到有关 CustomerStatus
class 构造函数的错误,因此我添加了默认保护的构造函数。
之后我开始收到错误:
Field 'k__BackingField' of entity type 'CustomerStatus' is readonly and so cannot be set.
这是我的CustomerStatus
class的内幕,如果有帮助的话:
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
class 内的 Type
和 ExpirationDate
属性上添加私有设置器,并结合 Ivan 的回答,它就像一个魅力。非常感谢!
您的尝试无效,因为拥有的类型 只能 通过它们的 owner 实体进行配置,更具体地说,通过它们自己的构建器由 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");
});
});
});