【问题标题】:EF6 Configuring a Required-to-Optional Relationship (One-to–Zero-or-OneEF6 配置必需到可选的关系(一对零或一
【发布时间】:2019-05-20 20:46:39
【问题描述】:

我有两个名为

的数据库表

段集 SegmentSetGeometry

它们都有名为SegmentSetId 的主键。 (SegmentSetGeometry(依赖)segmentSetId 是 SegmentSet(主)的外键)。

SegmentSet 可以有 0 或 1 个 SegmentSetGeometries

我有两个类代表这些表,称为SegmentSetSegmentSetGeometry

public class SegmentSet
{
    public long SegmentSetId { get; set; }
    // ...
    public virtual SegmentSetGeometry SegmentSetGeometry { get; set; }
}

public class SegmentSetGeometry
{
    public long SegmentSetId { get; set; }
    public DbGeometry Geometry { get; set; }

    public virtual SegmentSet SegmentSet { get; set; }
}

这是它们的配置:

public class SegmentSetConfiguration: EntityTypeConfiguration<SegmentSet>
{
    public SegmentSetConfiguration()
    {
        ToTable("SegmentSet");
        HasKey(x => x.SegmentSetId);

        // ...

        HasOptional(x => x.SegmentSetGeometry)
            .WithRequired(x => x.SegmentSet);
    }
}

public class SegmentSetGeometryConfiguration : EntityTypeConfiguration<SegmentSetGeometry>
{
    public SegmentSetGeometryConfiguration()
    {
        ToTable("SegmentSetGeometry");
        HasKey(x => x.SegmentSetId);
    }
}

当尝试从数据库中获取SegmentSet 时,会出现以下错误:

Invalid column name 'SegmentSet_SegmentSetId'.

我找到了这个参考https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/fluent/relationships,决定切换关系试了下:

public class SegmentSetConfiguration: EntityTypeConfiguration<SegmentSet>
{
    public SegmentSetConfiguration()
    {
        ToTable("SegmentSet");
        HasKey(x => x.SegmentSetId);

        // ...
    }
}

public class SegmentSetGeometryConfiguration : EntityTypeConfiguration<SegmentSetGeometry>
{
    public SegmentSetGeometryConfiguration()
    {
        ToTable("SegmentSetGeometry");
        HasKey(x => x.SegmentSetId);
        HasRequired(x => x.SegmentSet)
            .WithOptional(x=>x.SegmentSetGeometry);

    }
}

但还是不行。我正在使用他们给出的示例,但它不起作用,我查看了所有类似的堆栈溢出,但仍然不起作用

【问题讨论】:

    标签: c# entity-framework entity-framework-6 relationship


    【解决方案1】:

    要将这两者映射在一起,您应该从关系的所需一侧进行映射,并且只映射到那一侧。映射双方可能会导致 EF 有点乱码,这可能会导致您的问题。

    public class SegmentSet
    {
        public long SegmentSetId { get; set; }
        // ...
        public virtual SegmentSetGeometry Geometry { get; set; }
    }
    
    public class SegmentSetGeometry
    {
        public long SegmentSetId { get; set; }
        // ...
        public virtual SegmentSet SegmentSet { get; set; }
    }
    
    public class SegmentSetConfiguration: EntityTypeConfiguration<SegmentSet>
    {
        public SegmentSetConfiguration()
        {
            ToTable("SegmentSets");
            HasKey(x => x.SegmentSetId);
            // Note: Do not map the HasOptional here... Only map the required on the other side.
        }
    }
    
    public class SegmentSetGeometryConfiguration : EntityTypeConfiguration<SegmentSetGeometry>
    {
        public SegmentSetGeometryConfiguration()
        {
            ToTable("SegmentSetGeometries");
            HasKey(x => x.SegmentSetId);
            HasRequired(x => x.SegmentSet)
                .WithOptional(x=>x.Geometry);
    
        }
    }
    

    对于 1..0/1 关系,使用每个表上的 PK 应该可以按预期工作。

    编辑:检查实体配置是否正在加载也是值得的。这或许可以解释 EF 回归惯例的原因。在 DbContext 中:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Configurations.AddFromAssembly(GetType().Assembly);
    }
    

    以上假设实体类型配置与 DbContext 定义在同一个程序集中。否则:typeof(SegmentSetGeometryConfiguration).Assembly 可以解决问题。

    【讨论】:

    • 抱歉,我的问题可能不清楚,但在我阅读文档后,我从 SegmentSetConfiguration 中删除了流畅的 API,所以我实际上完全按照您的建议进行操作,但它不起作用。我认为这可能与查询有关,而不是与关系有关。我将更新问题以更清楚
    • 这很不寻常,因为我将上面的表结构设置为测试,它按预期工作而没有问题。以上是测试项目的复制粘贴。你用的是什么数据库引擎?另外,您确定正在加载 EntityTypeConfigs 吗?它可以解释 EF 回归惯例。 (编辑后的答案包括在内。)
    • EF Core 中这种关系的替代品是什么
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    相关资源
    最近更新 更多