0

我是EF的新手。我读了http://msdn.microsoft.com/en-us/data/gg193958.aspx并且仍然感到困惑。

我有一个现有的数据库,我正在编写一个 Code First 模型。我有带有 op_code Char(6) 主键的 Operators 表。在 Operator 类中,我将其命名为 OperatorCode,例如

[Key]
[Column("op_code",TypeName = "char")]
[DisplayName("Operator")]
public virtual string OperatorCode { get; set; }

在我的几个表中,我有 EnteredBy 和一些对 op_code 是 FK 的 ModifiedBy 列。

比如说,对于 Clients 表,我有这两个字段。

所以,我在底部的 Operator 类中添加了:

[InverseProperty("EnteredBy")]
public virtual ICollection<Client> ClientsEnteredBy { get; set; }

[InverseProperty("ModifiedBy")]
public virtual ICollection<Client> ClientsUpdatedBy { get; set; }

我在 Client 类中添加了以下内容:

public virtual Operator EnteredBy { get; set; }
public virtual Operator ModifiedBy { get; set; }

我收到有关 EnteredBy_OperatorCode 和 ModifiedBy_OperatorCode 列的运行时错误。

我应该修复什么 /add 让 EF 知道我的列名?

提前致谢。

4

1 回答 1

1

您在数据库中的外来列名称与 FK 名称的默认约定不匹配,即NavigationPropertyName_PrimaryKeyNameinTargetClass. 因为您的导航属性被调用EnteredBy并且ModifiedBy主键属性被调用OperatorCodeEF 期望 - 根据提到的约定 -EnteredBy_OperatorCode并且ModifiedBy_OperatorCode作为外键列。但是这些在数据库中不存在,这是您异常的原因。相反,您的 FK 列是EnteredByModifiedBy

因此,要解决问题,您必须重写约定。

如果您的模型中没有 FK 属性,请使用 Fluent API:

modelBuilder.Entity<Operator>()
    .HasMany(o => o.ClientsEnteredBy)
    .WithRequired(c => c.EnteredBy)    // or HasOptional
    .Map(m => m.MapKey("EnteredBy"));  // mapping for the FK column name

modelBuilder.Entity<Operator>()
    .HasMany(o => o.ClientsUpdatedBy)
    .WithRequired(c => c.ModifiedBy)    // or HasOptional
    .Map(m => m.MapKey("ModifiedBy"));  // mapping for the FK column name

(使用此映射,您可以删除该InverseProperty属性。)

另一种方法是将 FK 公开为模型中的属性。重命名导航属性并将其名称用于 FK 属性。然后可以使用数据注释进行映射。

Client课堂上:

[ForeignKey("EnteredByOperator")]
public string EnteredBy { get; set; }

[InverseProperty("ClientsEnteredBy")]
public virtual Operator EnteredByOperator { get; set; }

[ForeignKey("ModifiedByOperator")]
public string ModifiedBy { get; set; }

[InverseProperty("ClientsUpdatedBy")]
public virtual Operator ModifiedByOperator { get; set; }

并删除类中的InverseProperty属性Operator

除了数据注释,您还可以使用 Fluent API:

modelBuilder.Entity<Operator>()
    .HasMany(o => o.ClientsEnteredBy)
    .WithRequired(c => c.EnteredByOperator)    // or HasOptional
    .HasForeignKey(c => c.EnteredBy);

modelBuilder.Entity<Operator>()
    .HasMany(o => o.ClientsUpdatedBy)
    .WithRequired(c => c.ModifiedByOperator)    // or HasOptional
    .HasForeignKey(c => c.ModifiedBy);

如果这两种关系都需要,您将需要为至少一个关系禁用级联删除(附加.WillCascadeOnDelete(false)在其中一个映射的末尾),否则 SQL Server 将抛出一个错误,即不允许表之间的多个级联删除路径。

我建议使用“替代方法”(将外键作为属性公开),因为在大多数情况下它更容易使用。

于 2012-09-12T20:36:51.827 回答