2012-09-12 86 views
0

我是EF的新手。我读http://msdn.microsoft.com/en-us/data/gg193958.aspx仍然困惑。EF和字符PK/FK

我有一个现有的数据库,我正在写一个Code First模型。我有操作员表op_code字符(6)主键。在Operator类中,我将它命名为OperatorCode,例如

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

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

说,对于客户表我有这两个字段。

所以,我加入到运营商级的底部:

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

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

,我添加了以下内容的客户端类:

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

和我得到大约运行时错误EnteredBy_OperatorCode和ModifiedBy_OperatorCode列。

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

在此先感谢。

+1

你能发布异常吗? – CodingGorilla

+0

异常很长。我还在MSDN线程中发布了整个字符串http://social.msdn.microsoft.com/Forums/zh-CN/adodotnetentityframework/thread/a4090253-a5b7-466c-8f66-f5fc3b61cde8 – Naomi

+0

“执行命令定义时发生错误详情请参阅内部例外。“} – Naomi

回答

1

数据库中的外国列名与FK名称的默认约定不匹配,即NavigationPropertyName_PrimaryKeyNameinTargetClass。因为您的导航属性被称为EnteredByModifiedBy,主键属性被称为OperatorCode EF期望 - 根据上述约定 - EnteredBy_OperatorCodeModifiedBy_OperatorCode作为外键列。但那些不在数据库中,这是你的例外的原因。相反,您的FK栏是EnteredByModifiedBy

所以,要解决这个问题,你必须重写约定。

如果你没有你的模型使用流利的API在FK属性:

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属性。)

的另一种方法是揭露FKS作为模型中的属性。重命名导航属性并将其名称用于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; } 

并删除OperatorInverseProperty属性。

不是数据注解的,你也可以用流利的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会抛出一个错误,即表之间不允许有多个级联删除路径。

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