在DDD中,使实体的标识成为值对象是一种常见的设计。
示例:
public class FooId : ValueObject
{
public int Id { get; private set; }
}
public class Foo
{
public FooId FooId { get; private set; }
}
在EF6中,我可以使用以下代码映射此类类型:
modelBuilder.ComplexType<SomeType>()
.Property(x => x.SomeProperty)
...
(请参阅3 Reasons to Model Identity as A Value Object,IDDD)
编辑:IDDD in .Net
但是当我尝试映射Foo和FooId时,在迁移过程中出现以下错误
属性表达式'x => x.FooId.Id'无效。该表达式应表示一个属性:C#:'t => t.MyProperty'VB.Net:'Function(t)t.MyProperty'。指定多个属性时,请使用匿名类型:C#:'t => new {t.MyProperty1,t.MyProperty2}'VB.Net:'Function(t)New with {t.MyProperty1,t.MyProperty2}'。
我的配置:
public class FooConfiguration : EntityTypeConfiguration<Foo>
{
public FooConfiguration()
{
HasKey(x => x.FooId.Id);
}
}
public class FooContext : EntityTypeConfiguration<Foo>
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.ComplexType<FooId>();
modelBuilder.Configurations.Add(new FooConfiguration());
}
}
使用的包裹
答案 0 :(得分:1)
不幸的是,当前在Caused by: org.apache.commons.logging.LogConfigurationException: java.lang.ClassNotFoundException: org.apache.logging.log4j.jcl.LogFactoryImpl (Caused by java.lang.ClassNotFoundException: org.apache.logging.log4j.jcl.LogFactoryImpl)
at org.apache.commons.logging.LogFactory.createFactory(LogFactory.java:1276)
at org.apache.commons.logging.LogFactory$2.run(LogFactory.java:1065)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.commons.logging.LogFactory.newFactory(LogFactory.java:1062)
at org.apache.commons.logging.LogFactory.getFactory(LogFactory.java:497)
at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:685)
at org.apache.struts.validator.DynaValidatorForm.<clinit>(DynaValidatorForm.java:97)
... 31 more
Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.jcl.LogFactoryImpl
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1892)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1735)
at org.apache.commons.logging.LogFactory.createFactory(LogFactory.java:1131)
... 37 more
中是不可能的,您必须处理常规的原语。虽然可以在EF 6.x
中使用Value Conversions。
作为经典EF core 2.1
的替代方法,您可以尝试.Net Framework
,因为它允许使用值对象作为标识。从NHibernate
的角度来看,NHibernate
看上去比EF
更强大。
答案 1 :(得分:1)
EF可以自动识别复杂类型(值对象),您无需添加任何流利的api映射。
我给你一个来自this course, by Julie Lerman的例子
Address
是一个ValueObject:
public class Address
{
public string Street { get; private set; }
public string City { get; private set; }
public string StateProvince { get; private set; }
public string PostalCode { get; private set; }
}
SalesOrder
是我们的实体,它使用Address
复杂类型。
public class SalesOrder
{
public int SalesOrderId { get; private set; }
public DateTime OrderDate { get; private set; }
public DateTime? DueDate { get; private set; }
public string PurchaseOrderNumber { get; private set; }
public string Comment { get; private set; }
public Address ShippingAddress { get; private set; }
}
现在,如果您首先使用EF代码来构建数据库表,那么您将获得(迁移代码):
CreateTable("SalesOrder", c => new
{
SalesOrderId = c.Int(nullable: false),
OrderDate = c.DateTime(nullable: false),
DueDate = c.DateTime(),
PurchaseOrderNumber = c.String(),
Comment = c.String(),
ShippingAddress_Street = c.String(),
ShippingAddress_City = c.String(),
ShippingAddress_StateProvince = c.String(),
ShippingAddress_PostalCode = c.String(),
})
.PrimaryKey(t => t.SalesOrderId);
请注意,EF将所有地址字段直接添加到表中。
您不需要任何其他流利的api映射即可让实体框架将Address
字段添加到表中,以上是默认行为。
DbContext
的外观如下:
public class OrderContext: DbContext
{
public OrderContext() : base("connectionStringName") { }
DbSet<SalesOrder> Orders { get; set; }
}