【问题标题】:Entity Framework one-to-one with a class that is sometimes independent实体框架与有时独立的类一对一
【发布时间】:2016-07-05 22:02:57
【问题描述】:

我有一个父类ComponentDesign:

public class ComponentDesign
{
    public string Name { get; set; }

    public virtual JobFile DesignFile { get; set; }
    public int? DesignFileId { get; set; }

    public Pdf PdfFile { get; set; }
    public int? PdfFileId { get; set; }

    public JobFile SealedPdfFile { get; set; }
    public int? SealedPdfFileId { get; set; }

    public int Id { get; set; }

    public int JobId { get; set; }
}

还有一个子类JobFile(其中Pdf是一个子类):

public class JobFile
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }

    public ComponentDesign ComponentDesign { get; set; }
    public int? ComponentDesignId { get; set; }

    public int? JobId { get; set; }
}

这些类使用实体框架存储在关系数据库中。我想在关系的两边都有导航属性,这样我就可以随意说componentDesign.PdfFile或jobFile.ComponentDesign。

ComponentDesign 中JobFile 类型的每个属性都是可选的,JobFile will only ever belong to oneComponentDesign. However, aJobFilemay be free-standing, not belonging to anyComponentDesign(sojobFile.ComponentDesign 将为空)。

我正在努力解决如何使用 Fluent API 来配置这种关系。这是一对一的。是否可以在关系的双方都有导航属性?请记住,JobFile 可以是独立的(所以jobFile.ComponentDesign 并不总是相关的),所以有属于ComponentDesigns 的JobFiles 和不属于的JobFiles。最接近我的感觉是:

modelBuilder.Entity<ComponentDesign>()
            .HasOptional(componentDesign => componentDesign.DesignFile)
            .WithRequired(jobFile => jobFile.ComponentDesign);

但这似乎表明jobFile.ComponentDesign 始终是必需的,但事实并非如此。我很犹豫是否尝试它,因为它会产生一些实质性的迁移,所以我想先获得输入。在这种情况下,我的 Fluent API 配置应该是什么样的?

【问题讨论】:

  • 要在实体框架中创建两个对象类之间的关系,或者说数据表,您可以使用带有类类型的虚拟词。我相信您可以找到针对您的问题的虚拟属性的结果。

标签: c# entity-framework entity-framework-6 one-to-one


【解决方案1】:

只是为了让我了解这些关系:

ComponentDesign -> JobFile = 可选。

JobFile -> ComponentDesign = 可选。

这是零或一到零或一 ([0/1]-[0/1]) 的关系。

这可以通过以下方式实现,使用 fluent API 中的.WithOptionalPrincipal 方法。 1-0的关系,哪一端是主端一目了然;与 1-∞ 关系相同。 ∞-∞ 关系没有主体端,因为创建的隐藏表控制着每个关系之间的关系。对于 0/1-0/1 或 1-1 关系,这并不明显,因此您必须告诉数据库使用哪个端作为关系的主体端。其中,主体负责启动和维护表之间的关系。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure ComponentDesign & JobFile entity
    modelBuilder.Entity<ComponentDesign>()

        // Mark JobFile property optional in ComponentDesign entity.
        .HasOptional(cd => cd.DesignFile)

        // Mark ComponentDesign property optional in JobFile entity.
        .WithOptionalPrincipal(jf => jf.ComponentDesign); 
}

或者,您可以为每个实体创建一个EntityTypeConfiguration&lt;&gt; 类来分离关系,如果有很多需要整理的话。虽然这确实分散了关系,但它更具可扩展性,因为一旦配置上下文,这些配置类就可以通过 MEF 注入。只是未来发展的一个想法。

如果您从 JobFile 端配置关系,您将使用 .WithOptionalDependent 来正确设置导航,而不是 .WithOptionalPrincipal。这完全取决于您从哪一方配置关系。 ComponentDesign 实体对JobFile 实体的依赖比JobFile 实体对ComponentDesignentity 的依赖程度要高得多;因此它应该被配置为主体。

如上述任一 cmets 所述,复杂属性应使用 virtual 关键字修饰。这个惰性加载属性,并且当类被实例化时,它会将初始值设置为null。

将数据库克隆到测试服务器,解决这一问题,然后在生产模型上实施更改;这样在迁移数据库时就不会丢失数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多