Bug #69192 After inserting the record, that record does not access its assocations.
Submitted: 10 May 2013 10:11 Modified: 17 Jun 2013 22:55
Reporter: Jae sung Chugn Email Updates:
Status: No Feedback Impact on me:
None 
Category:Connector / NET Severity:S2 (Serious)
Version:6.6.5, 6.7.2 OS:Microsoft Windows (Windows 8)
Assigned to: Assigned Account CPU Architecture:Any

[10 May 2013 10:11] Jae sung Chugn
Description:
The table Payment has 3 associations such as User, PaymentMethod, and PaymentType (that are connected by foreign keys).

            var payment = new Payment
            {
                C_paymentguid = Guid.NewGuid().ToString("N"),
                for_userid = 9,
                method_paymentmethodid = 1,
                paidby_paymenttypeid = 2,
                label = "",
                rowversion = DateTime.Now
            };

            entities.Payments.Add(payment);
            entities.SaveChanges();

            var cellphone = payment.User.cellphone; <-

System.NullReferenceException occurs when excuting the last statment.

How to repeat:
1. Prepare 4 tables that the one has three foreign key relations to the others.
2. Add a record to the table that has three foreign keys.
3. Call SaveChanges();
4. Access association properties through that record. 
5. System.NullReferenceException

Suggested fix:
1. After insert(s) and save changes, the local instance of the instances can access its associations.

2. Local.Remove() or Clear() does not affect at all. Fix it that after remove by Local.Remove() or Clear(), retrive data from database not from local cache.
[17 May 2013 22:55] Gabriela Martinez Sanchez
Hi Jae sung Chugn:

I tried to reproduce the issue that you described, I had to assumed the definition of the context by your description.

Here's the code that I used:

//Definition of the entities

 public class PaymentMethod
  {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int method_paymentmethodid { get; set; }
    public string name { get; set; }
  }

 public class PaymentType {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int paidby_paymenttypeid { get; set; }
    public string name { get; set; }
  }

  public class User
  {
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int userId { get; set; }
    public string name { get; set; }
    public string cellphone { get; set; }
  }

 public class Payment
  {
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]    
    public Guid paymentId { get; set; }   
    public string label {get; set;}
    public DateTime rowversion;    
    
    public int userId { get; set; }
    [ForeignKey("userId")]
    public User User { get; set; }

    public int paidby_paymenttypeid { get; set; }
    [ForeignKey("paidby_paymenttypeid ")]
    public PaymentType PaymentType { get; set; }

    [ForeignKey("method_paymentmethodid")]
    public PaymentMethod PaymentMethod { get; set; }
    public int method_paymentmethodid { get; set; }
    
  }

//definition of the context

public class PaymentContext : DbContext
 {
    public DbSet<Payment> Payments { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<PaymentMethod> PaymentMethods {get; set;}
    public DbSet<PaymentType> PaymentTypes { get; set; }
 }

On the main code:

public class Program
{
  static void Main(string[] args)
  {
     using (var db = new PaymentContext())
      {
        db.Database.Delete();
        db.Database.CreateIfNotExists();

        var user = new User
        {
          name = "my user",
          cellphone = "some cellphone"
        };

        var paymentmethod = new PaymentMethod
        {
          name = "some payment  method"
        };

        var paymentType = new PaymentType
        {
          name = "some payment type"
        };

        db.Users.Add(user);
        db.PaymentMethods.Add(paymentmethod);
        db.PaymentTypes.Add(paymentType);
        db.SaveChanges();

        var payment = new Payment
            {
                paymentId = Guid.NewGuid(),
                userId = 1,
                method_paymentmethodid = 1,
                paidby_paymenttypeid = 1,
                label = "",
                rowversion = DateTime.Now
            };

        db.Payments.Add(payment);
        db.SaveChanges();

        var paymentRow = db.Payments.First();

        var cellphone = payment.User.cellphone;
        Console.WriteLine("Cellphone's user" + cellphone);  
      }
    }
  } 
}

The output of the program is as expected the value on the Cellphone column for the first user.

Regarding this comment:
 After insert(s) and save changes, the local instance of the instances can access its associations.

You need to be very careful with when using the Local property. A local Property:
   - Will always access the data that has not been removed from a DbSet.
   - Will always access the data that has been added to a DbSet even if it does not exist in the Database yet.

But if you use a DbSet query:
- An entity that has been marked with Removed will always be included.
- An entity that has not yet been added won't be included.

Thus when using Local.Remove() won't affect the records on your database. You can do a context.Entry(instance).GetDatabaseValues() to synchronize the records on your database with the ones that are being tracked in your context.

Hope you can give us more information on the issue you're having.
[18 Jun 2013 1:00] Bugs System
No feedback was provided for this bug for over a month, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".