c# - Entity Framework 与有时独立的类一对一

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

我有一个父类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; }
}

还有一个 child 类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; }
}

这些类使用 Entity Framework 存储在关系数据库中。我希望关系双方都有导航属性,这样我就可以说 componentDesign.PdfFilejobFile.ComponentDesign随意。

JobFile 类型的每个属性在ComponentDesign是可选的,并且 JobFile will only ever belong to one组件设计. However, a作业文件 may be free-standing, not belonging to any组件设计(so jobFile.ComponentDesign`将为空)。

我正在努力解决如何使用 Fluent API 来配置这种关系。它是一对一的。是否可以在关系的两侧都具有导航属性?请记住 JobFile可以是独立的(因此jobFile.ComponentDesign并不总是相关的),所以有JobFile属于 ComponentDesign 的 s和那些没有的。我觉得我最接近的是:

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

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

最佳答案

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

ComponentDesign -> JobFile = 可选。

JobFile -> ComponentDesign = 可选。

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

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

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<>如果有很多需要排序的话,每个实体的类可以分离出关系。虽然这确实分散了关系,但它更具可扩展性,因为一旦配置了上下文,就可以通过 MEF 注入(inject)这些配置类。只是对 future 发展的一个想法。

如果您从 JobFile 端配置关系,则可以使用 .WithOptionalDependent ,为了正确设置导航,而不是 .WithOptionalPrincipal 。这完全取决于您从哪一方配置关系。 ComponentDesign实体依赖 JobFile实体远多于JobFile实体依赖 ComponentDesign实体;因此应该将其配置为主体。

正如上面的评论之一所述,复杂的属性应该用 virtual 来装饰。关键词。这个延迟加载属性,并且当类实例化时,它会将初始值设置为 null .

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

关于c# - Entity Framework 与有时独立的类一对一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38213561/

相关文章:

c# - 多对多导航属性为空

c# - 在类库中使用 Automapper 进行 Ninject

c# - 使用动态对象反序列化 JSON

c# - 一个 View 中的 ASP.NET MVC 多个模型

c# - iis 仅返回 Entity Framework 响应中的第一个对象

mysql - Entity Framework 电动工具 Beta 4 与非 - 使用 MySql

entity-framework - EF 中的列名无效

c# - EntityFramework EF 不让我重新搭建脚手架

c# - 如何将任何对象类型转换为实际类型

c# - ASP MVC : ViewModel index using master detail linq statement