我是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知道我的列名?
提前致谢。
答案 0 :(得分:1)
数据库中的外键列名与FK名称的默认约定NavigationPropertyName_PrimaryKeyNameinTargetClass
不匹配。因为您的导航属性称为EnteredBy
和ModifiedBy
,并且主要属性称为OperatorCode
EF期望 - 根据上述惯例 - EnteredBy_OperatorCode
和ModifiedBy_OperatorCode
外键列。但是那些不存在于数据库中的是你的例外原因。相反,您的FK列为EnteredBy
和ModifiedBy
。
因此,要解决问题,必须覆盖约定。
如果您的模型中没有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将抛出多个级联删除的错误不允许表格之间的路径。
我建议使用“替代方法”(将外键公开为属性),因为在大多数情况下它更容易使用。