编程语言
首页 > 编程语言> > c# – Entity Framework 5 Fluent API – 配置单向关系

c# – Entity Framework 5 Fluent API – 配置单向关系

作者:互联网

我不能为我的生活弄清楚这一点. MSDN上的文章不清楚,似乎已经过时了.我正在使用EF 5,我正在尝试为以下内容建立单向关系.所以这就是我到目前为止所拥有的.

public sealed class Capture {
    /// <summary>
    /// Get and Set Capture's Unique Identifier.
    /// </summary>
    public int Id { get; set; }

    /// <summary>
    /// Get and Set Capture's Operating System.
    /// </summary>
    public OperatingSystem OperatingSystem { get; set; }
}

public sealed class OperatingSystem {
    /// <summary>
    /// Operating System's Unique Identifier.
    /// </summary>
    public int Id { get; set; }
}

internal sealed class EntityCaptureConfiguration : EntityTypeConfiguration<Capture> {
    /// <summary>
    /// Create an Entity Capture Configuration.
    /// </summary>
    public EntityCaptureConfiguration() {
        this.ToTable("Capture");
        this.HasKey(m => m.Id);

        this.Property(m => m.Id).HasColumnName("Id");

        this.HasRequired(m => m.OperatingSystem).WithRequiredDependent().Map(m => {
            m.ToTable("OperatingSystem");
            m.MapKey("OperatingSystemId");
        });
    }
}

编译并运行,我得到以下运行时异常:“错误3034:从第16,46行开始映射片段时出现问题:可能有不同键的两个实体映射到同一行.确保这两个映射片段映射到AssociationSet的两端到相应的栏目.“

我不禁注意到,实际上没有明确的方法来表明我想使用2个特定键加入这两个表.我的意思是我在哪里指定子表中的键用于父表中的连接?

这是我需要帮助的:

>我不想在名为的Capture类型上公开属性
“OperatingSystemId”. “OperatingSystem”属性不仅仅是
足够.
>我不希望Capture之间存在双向关系
和OperatingSystem类型.只有单向关系
从Capture到OperatingSystem是必需的.
>我不想在操作数据库中创建一个列
系统表名为“CaptureId”.我甚至不知道为什么会这样
需要,但我读了一篇建议这样做的文章
办法.
>生成的SQL连接应该是INNER JOIN而不是OUTER
加入.
>我真的需要在上面定义OperatingSystem属性
捕获类型为虚拟?我不希望这个属性是懒惰的
加载.
>奖金指向可以向我解释此例外的人,因为
我完全迷失了.谷歌搜索对于Fluent API毫无希望.一世
如果我使用的是设计师,我会得到很多热门话题,但我认为是这样
不相关,因为所有结果都表明要重新生成模型,
我不认为这适用于此.

更新:
我可能不清楚这一点.我已经在SQL Server中设置了数据库模型.我试图了解如何在不使用设计器的情况下使用Fluent API为现有数据库模型配置EF上下文.我知道如果我使用设计器,我可以简单地要求它从数据库生成我的上下文.那不是我想要的.对于那些好奇的原因 – 因为我想了解如何使用Fluent API来实现它.

UPDATE2:
所以,看起来我已经设置了,如果在我的查询中我指定了一个导航属性的过滤器,EF正确生成连接.如果不这样做,查询中不会生成任何联接.无论如何,导航财产仍然没有被填充!

提前感谢一堆.

解决方法:

因此,如果您没有像我一样使用ORM并且使用像MyBatis或类似的数据映射器这样的背景,那么解决方案就是这个,给出了我的问题中的示例.

首先,您需要无法将实体类型声明为密封,并且任何参与关联的属性都需要声明为虚拟.这是因为EF将在运行时使用动态代理扩展类型,并使用动态代理覆盖您的属性以启用延迟加载:

public class Capture {
    /// <summary>
    /// Get and Set Capture's Unique Identifier.
    /// </summary>
    public int Id { get; set; }

    /// <summary>
    /// Get and Set Capture's Operating System.
    /// </summary>
    public virtual OperatingSystem OperatingSystem { get; set; }
}

public class OperatingSystem {
    /// <summary>
    /// Operating System's Unique Identifier.
    /// </summary>
    public int Id { get; set; }
}

如果不这样做,则不会抛出任何错误,但EF将始终将关联的属性设置为null.

其次,除非您的关联属性尚未配置为映射,否则不要将其映射到特定表,因为EF会抱怨同一个表实际上映射了两次.在我的示例中,我已经自己映射了OperatingSystem类型,并且在设置关联时,我再次映射它:

internal sealed class EntityCaptureConfiguration : EntityTypeConfiguration<Capture> {
    /// <summary>
    /// Create an Entity Capture Configuration.
    /// </summary>
    public EntityCaptureConfiguration() {
        this.ToTable("Capture");
        this.HasKey(m => m.Id);

        this.Property(m => m.Id).HasColumnName("Id");

        this.HasRequired(m => m.OperatingSystem).WithRequiredDependent().Map(m => m.MapKey("OperatingSystemId"));
    }
}

最后,如果您必须绝对声明您的实体类型是密封的,并且您不希望将任何属性声明为虚拟 – 您无论如何都无法在密封类型上 – 在您的上下文配置中,禁用代理和延迟加载:

public sealed class EntityDefaultContext : DbContext {    
    /// <summary>
    /// Model Creating Event Handler.
    /// </summary>
    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        var entityCaptureConfiguration = new EntityCaptureConfiguration();
        var entityOperatingSystemConfiguration = new EntityOperatingSystemConfiguration();

        modelBuilder.Configurations.Add(entityOperatingSystemConfiguration);
        modelBuilder.Configurations.Add(entityCaptureConfiguration);

        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.ProxyCreationEnabled = false;
    }
}

这就是所有人.我希望将来可以帮助像我这样的人.

标签:c,net,entity-framework-5,ef-code-first
来源: https://codeday.me/bug/20190718/1494547.html