none
Using InverseProperty on self-referencing entity in 4.3 RRS feed

  • Question

  • Assume a self-referencing Entity with the following ForeignKey and InverseProperty data annotations.  (I realize the data annotations here are not strictly necessary, but bear with me.)

    public class Employee {
      public int EmployeeID { get; set; }
      public string LastName { get; set; }
      public string FirstName { get; set; }
    
      [ForeignKey("ReportsTo")]
      public int? ReportsToEmployeeID { get; set; }
    
      [InverseProperty("Manages")]
      public virtual Employee ReportsTo { get; set; }
    
      [InverseProperty("ReportsTo")]
      public virtual ICollection<Employee> Manages { get; set; }
    }

    In EF 4.2 this markup worked as expected (or maybe I should say as we wanted), however a NullReferenceException is thrown in EF 4.3 when trying to query this entity.   This occurs either when creating a new database or pointing to an existing one.  The problem appears to be the InverseProperty annotations, but it's not clear what's wrong with them.   What are we doing wrong?

    Here's the stack trace:

      EntityFramework.dll!System.Data.Entity.Internal.RetryAction<System.Data.Entity.Internal.InternalContext>.PerformAction(System.Data.Entity.Internal.InternalContext input) + 0x94 bytes 
      EntityFramework.dll!System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(System.Action<System.Data.Entity.Internal.InternalContext> action) + 0x115 bytes 
      EntityFramework.dll!System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase() + 0x71 bytes 
      EntityFramework.dll!System.Data.Entity.Internal.InternalContext.Initialize() + 0x2b bytes 
      EntityFramework.dll!System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(System.Type entityType) + 0x23 bytes 
      EntityFramework.dll!System.Data.Entity.Internal.Linq.InternalSet<_EFSample.Employee>.Initialize() + 0x7e bytes 
      EntityFramework.dll!System.Data.Entity.Internal.Linq.InternalSet<_EFSample.Employee>.GetEnumerator() + 0x22 bytes 
      EntityFramework.dll!System.Data.Entity.Infrastructure.DbQuery<_EFSample.Employee>.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator() + 0x5c bytes 

    Thanks.

    Thursday, March 1, 2012 8:04 PM

All replies

  • Hi Kim,

    Please try the code as following:

    public class Employee {
      public int EmployeeID { get; set; }
      public string LastName { get; set; }
      public string FirstName { get; set; }
    
      [ForeignKey("ReportsTo")]
      public int? ReportsToEmployeeID { get; set; }
    
      [Required]
      public virtual Employee ReportsTo { get; set; }
    
      [InverseProperty("ReportsTo")]
      public virtual ICollection<Employee> Manages { get; set; }
    }
    Have a nice day.

    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, March 5, 2012 7:01 AM
    Moderator
  • Thanks for the reply, Alan. 

    I'm curious, though, as to what the rules are here.  We have a T4 template generating class definitions, and we need to know what rules we should follow when adding data annotations.  The MSDN description of the RequiredAttribute does not indicate it should be used here.  The descriptions for both the ForeignKey and InverseProperty attributes indicate we are using them correctly.  We were apparently using them correctly in versions prior to EF 4.3.  What has changed in 4.3 that causes this markup to no longer work?

    Monday, March 5, 2012 7:28 PM
  • Hi Kim,

    Thanks for your feedback.

    In fact, there is not need to use "InVerseProperty" in your sample.

    ===================

    InversePropertyAttribute is placed on a navigation property to specify the property that represents the other end of a relationship. You typically need it only if you have multiple relationships between the same types.

    http://msdn.microsoft.com/en-us/library/gg197525(v=vs.103).aspx

    ===================

    There just one relationships in your entity.

    public class Employee { public int EmployeeID { get; set; } public string LastName { get; set; } public string FirstName { get; set; } [ForeignKey("ReportsTo")] public int? ReportsToEmployeeID { get; set; } //[Required] public virtual Employee ReportsTo { get; set; } //[InverseProperty("ReportsTo")] public virtual ICollection<Employee> Manages { get; set; } }

    Yes, In order to fix issues in mapping configuration, there are some changes. Here is another change

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, March 6, 2012 8:56 AM
    Moderator
  • Hi Kim,

    Any updates for your question now.

    Have a nice day.


    Alan Chen[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, March 16, 2012 8:36 AM
    Moderator
  • No updates.

    I removed your "mark as answer" because my questions from March 5 still stand.  I am still frustrated that Microsoft cannot adequately document both the breaking changes between 4.2 and 4.3, and the correct usage of these attributes.  I realize these are not your problems, so thank you for your help.

    Friday, March 16, 2012 4:15 PM