2013-10-07 54 views
3

在這一個上再次撕裂我的頭髮......使用EF 5代碼首先,在代碼中構建模型 - 編譯,因此它在語法上是正確的,但是在出現異常時代碼構建模型。下面是實體類(我也有vaidation屬性,但他們在這裏刪除了可讀性):實體框架5代碼首先無法讓模型正常工作

[Table("USERS")] 
public class User : IPEntity 
{ 
    #region Constructor (needs to initialize list objects for related entities) 

    public User() 
    { 
     this.Profiles = new List<Profile>(); 
     this.ProfileDivs = new List<ProfileDiv>(); 
     this.ProfileDepts = new List<ProfileDept>(); 
    } 

    #endregion 

    #region Entity properties and validation attributes 

    [Key] 
    public long UserId { get; set; } 

    public long PclientId { get; set; } 

    public string UserName { get; set; } 

    public string UserDescription { get; set; } 

    public long? EmpId { get; set; } 

    public string MustChangePassword { get; set; } 

    public long? FailedLogins { get; set; } 

    public DateTime? LastLogin { get; set; } 

    public long? SequenceNumber { get; set; } 

    public string AllDivs { get; set; } 

    public string AllDepts { get; set; } 

    public string UserRole { get; set; } 

    public DateTime? BeginSupport { get; set; } 

    public DateTime? EndSupport { get; set; } 

    public string OneTimeAccess { get; set; } 

    public long? ClonedFromUser { get; set; } 

    public string Email { get; set; } 

    public string ResetEmail { get; set; } 

    public DateTime? ResetTimeout { get; set; } 

    public long? ChallengeFailures { get; set; } 

    public string PermUserRole { get; set; } 

    public DateTime? PasswordChangedDate { get; set; } 

    public virtual ICollection<Profile> Profiles { get; set; } 

    public virtual ICollection<ProfileDiv> ProfileDivs { get; set; } 

    public virtual ICollection<ProfileDept> ProfileDepts { get; set; } 

    public virtual WorkSession WorkSession { get; set; } 

} 

模型構建器類:

public class User_Map : EntityTypeConfiguration<User> 
{ 
    public User_Map() 
    { 
     this.ToTable("USERS"); 

     this.HasKey(t => new { t.UserId }); 

     this.Property(t => t.UserId) 
      .HasColumnName("USER_ID") 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None) 
      .IsRequired(); 

     this.Property(t => t.UserName) 
      .HasColumnName("USERNAME") 
      .IsRequired() 
      .HasMaxLength(25); 

     this.Property(t => t.PclientId) 
      .HasColumnName("PCLIENT_ID"); 

     this.Property(t => t.EmpId) 
      .HasColumnName("EMP_ID"); 

     this.Property(t => t.MustChangePassword) 
      .HasColumnName("MUST_CHANGE_PASSWORD") 
      .HasMaxLength(1); 

     this.Property(t => t.UserDescription) 
      .HasColumnName("USER_DESCRIPTION") 
      .HasMaxLength(80); 

     this.Property(t => t.FailedLogins) 
      .HasColumnName("FAILED_LOGINS"); 

     this.Property(t => t.LastLogin) 
      .HasColumnName("LAST_LOGIN"); 

     this.Property(t => t.SequenceNumber) 
      .HasColumnName("SEQUENCE_NUMBER"); 

     this.Property(t => t.AllDivs) 
      .HasColumnName("ALL_DIVS") 
      .HasMaxLength(1); 

     this.Property(t => t.AllDepts) 
      .HasColumnName("ALL_DEPTS") 
      .HasMaxLength(1); 

     this.Property(t => t.UserRole) 
      .HasColumnName("USER_ROLE") 
      .HasMaxLength(2); 

     this.Property(t => t.BeginSupport) 
      .HasColumnName("BEGIN_SUPPORT"); 

     this.Property(t => t.EndSupport) 
      .HasColumnName("END_SUPPORT"); 

     this.Property(t => t.OneTimeAccess) 
      .HasColumnName("ONE_TIME_ACCESS") 
      .HasMaxLength(1); 

     this.Property(t => t.ClonedFromUser) 
      .HasColumnName("CLONED_FROM_USER"); 

     this.Property(t => t.Email) 
      .HasColumnName("EMAIL") 
      .HasMaxLength(60); 

     this.Property(t => t.ResetEmail) 
      .HasColumnName("RESET_EMAIL") 
      .HasMaxLength(60); 

     this.Property(t => t.ResetTimeout) 
      .HasColumnName("RESET_TIMEOUT"); 

     this.Property(t => t.ChallengeFailures) 
      .HasColumnName("CHALLENGE_FAILURES"); 

     this.Property(t => t.PermUserRole) 
      .HasColumnName("PERM_USER_ROLE") 
      .HasMaxLength(2); 

     this.Property(t => t.PasswordChangedDate) 
      .HasColumnName("PASSWORD_CHANGED_DATE"); 

     this.HasOptional(t => t.WorkSession) 
      .WithRequired(t => t.User); 

     // TODO: This is syntactically correct but model blows up! 

     this.HasMany(t => t.Profiles) 
      .WithRequired(t => t.User) 
      .HasForeignKey(t => t.UserId); 

    } 
} 

當模型生成器類的構造函數執行,我得到扔到線以上(註釋後)以下異常:

The expression 't => t.User' is not a valid property expression. 
The expression should represent a property: C#: 't => t.MyProperty' 
VB.Net: 'Function(t) t.MyProperty'. 

的配置文件實體很簡單:

[Table("PROFILE")] 
public class Profile : IPEntity 
{ 
    [Key, Column(Order = 0)] 
    [ForeignKey("UserId")] 
    public long UserId { get; set; } 

    [Key, Column(Order = 1)] 
    public string FunctionalArea { get; set; } 

    public int RightsId { get; set; } 

    public User User; 

} 

我一直在這上打了兩三天,如果有人能發現我的錯誤,我會非常感激!

謝謝, 彼得

更新:我發現了一個骨爲首的錯誤讀取this post,因爲我已經宣佈的東西作爲一個領域,而不是財產......但現在我得到一個不同的異常,我做不明白:

The navigation property 'UserId' is not a declared property on type 'Profile'. 
Verify that it has not been explicitly excluded from the model and that 
it is a valid navigation property. 

這讓我感到困惑,因爲UserId是Profile上聲明的屬性...?

第二次更新:

我明白了異常,但(因爲沒有內部異常詳細)不能確定它是從哪裏過來。我改變了User_map類包括:

 this.HasMany(t => t.Profiles) 
      .WithRequired(t => t.User) 
      .HasForeignKey(t => t.UserId) 
      .WillCascadeOnDelete(false); 

和Profile_map類包括:

 this.HasRequired(t => t.User) 
      .WithMany() 
      .HasForeignKey(t => t.UserId) 
      .WillCascadeOnDelete(false); 

因爲我與現有數據庫的工作,我堅持的財產「用戶ID」是一個這兩個表中的外鍵(在用戶表中它是用於配置文件表的外鍵,在配置文件表中它是用戶表的外鍵)。我在兩種情況下都添加了.WillCascadeOnDelete(false)以防出現某種循環性問題。就像我說過的,我無法確定哪個映射正在吹起來,對這兩個構造函數的調用都毫無例外地通過,只有在上下文中的OnModelCreating覆蓋時纔會拋出異常。這裏是越權:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 

     var mbProfile = new Profile_map(); 
     modelBuilder.Configurations.Add(mbProfile); 

     var mbUser = new User_Map(); 
     modelBuilder.Configurations.Add(mbUser); 

     base.OnModelCreating(modelBuilder); 
    } 

我知道我仍然是一個新手,EF,但我不能發現問題(當然,尚未反正...)再次

感謝。

回答

14
public User User; 

應該是一個財產而不是場 - 所有其他人一樣:)

public User User { get; set; } 

隨着virtual最好(允許延遲加載),因爲你已經打上所有的導航屬性virtual

編輯有關更新的

導航屬性UserId異常會談,並抱怨說,它是不是一個「有效的導航屬性」。事實上,這不是一個有效的導航屬性。例外情況表示您可能在WithRequired方法中使用了UserId(而不是User)。你應該仔細看看。

+0

是的,謝謝,我發現通過閱讀另一個問題,但現在我得到另一個例外,這是更令人困惑... –

+0

@PeterHowe:看看我的編輯上面有關你的後續異常。 – Slauma

+0

我在另一個編輯中添加了更多細節,希望能夠揭示出一些東西(可能是我做過的一些愚蠢的...) –

0

彼得,關於你對兩個「UserId」列的問題,你說他們都是外鍵。我不認爲你是對的。 User.UserId標有[Key],它是User類中唯一標記的方式。它必須是User表的主要ID。在Profile班上,您有UserIdFunctionalArea標有[Key]。這意味着Profile表有一個聯合主鍵,其中一個是User表的UserId列的外鍵。

這種設計非常好。但是,爲了在UserProfile記錄之間有一個關係,其中Profile記錄是父記錄,那麼您的User表中必須有兩列引用Profile表的兩個主鍵,並且這些列中的NEITHER可以是UserIdUser表的列,否則您將有循環依賴關係,無法創建任一記錄。底線是,UserProfile表之間沒有兩個關係,只有一個。所以從您的Profile_map類刪除以下塊:

this.HasRequired(t => t.User) 
    .WithMany() 
    .HasForeignKey(t => t.UserId) 
    .WillCascadeOnDelete(false); 

這應該修復它的權利了! ;)