EF和角色PK / FK

时间:2012-09-12 19:48:07

标签: entity-framework

我是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列的运行时错误。

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

提前致谢。

1 个答案:

答案 0 :(得分:1)

数据库中的外键列名与FK名称的默认约定NavigationPropertyName_PrimaryKeyNameinTargetClass不匹配。因为您的导航属性称为EnteredByModifiedBy,并且主要属性称为OperatorCode EF期望 - 根据上述惯例 - EnteredBy_OperatorCodeModifiedBy_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将抛出多个级联删除的错误不允许表格之间的路径。

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