gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 13:39:13 25 4
gpt4 key购买 nike

我这辈子都弄不明白。 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 个特定的键连接这 2 个表。我的意思是我究竟应该在哪里指定子表中的键以用于父表中的连接?

以下是我需要的帮助:

  1. 我不想公开名为 Capture 类型的属性“OperatingSystemId”。 "OperatingSystem"属性超过够了。

  2. 我不希望Capture之间存在双向关系和操作系统类型。只有单向关系需要从 CaptureOperatingSystem

  3. 我不想在操作的数据库中创建列名为“CaptureId”的系统 表。我什至不知道这是为什么需要,但我在某处读到一篇文章建议这样做方式。

  4. 生成的 SQL 连接应该是 INNER JOIN 而不是 OUTER加入。

  5. 我真的需要在捕获类型为虚拟?我不想让这个属性变得懒惰已加载。

  6. 奖金指向可以向我解释此异常的人,因为我完全迷路了。谷歌搜索 Fluent API 毫无希望。我如果我使用设计师,我会得到很多点击,但我认为它是不相关,因为所有结果都建议重新生成模型,我认为这里不适用。

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

更新 2:因此,看起来像我设置的那样,如果在我的查询中我在导航属性上指定了过滤器,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# - Entity Framework 5 Fluent API - 配置单向关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12994500/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com