如何使用流利的API在EF6中映射值对象身份?

时间:2018-10-09 07:13:11

标签: mysql entity-framework-6 domain-driven-design ef-migrations

在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 ObjectIDDD

  

编辑: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());
    }
}  

使用的包裹

  • EntityFramework 6.2.0
  • MySql.Data 6.10.7
  • MySql.Data.Entity 6.10.7

2 个答案:

答案 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; }
}