0

I work on my solution based on ASP.NET MVC with EF Code First.

I have the following model classes:

public class Request
{
    [Key]
    public virtual int RequestID { get; set; }
    public virtual string BudgetNumber { get; set; }
    public virtual string SiteCustom { get; set; }
    public virtual Vehicle Vehicle { get; set; }
}

public class Vehicle
{
    public int VehicleID { get; set; }
    public string DesignationFr { get; set; }
    public string DesignationNl { get; set; }
    public string DesignationEn { get; set; }
}

I need to log user modifications. For example, if user changed the SiteCustom value of the Request, I can easily track it with the code below. So inside the SaveChanges I intercept every added & modified entries.

    public override int SaveChanges() 
    {
        ChangeTracker.DetectChanges(); // Important!
        System.Data.Objects.ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext;
        List<ObjectStateEntry> objectStateEntryList = ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified).ToList();

        foreach (ObjectStateEntry entry in objectStateEntryList)
        {
            if (entry.IsRelationship)
            {

            }
            if (!entry.IsRelationship)
            {
                if (entry.Entity is Request) 
                {
                    var request = (Request)entry.Entity;
                    ...
                }
            }
        }
        return base.SaveChanges();
    }

As you can see in the code above, when the entry is not a relationship, I can easily retrieve the entity behind it.

My problem: when the user modified the Vehicle property of the request this is a relationship and I didn't succeed to retrieve the entities when this is a relationship. I mean not only retrieve the key values of the 2 parts of the relationship but all the fields of the entities. Is it possible?

Bronzato
  • 9,438
  • 29
  • 120
  • 212

1 Answers1

0

I figured it out. You must use Include to track the changes. For instance:

var re = ctx.Requests.Include(i => i.Vehicle).Where(i => i.RequestID == 1).FirstOrDefault(); //do no use find
//var re = ctx.Requests.Find(1);

 re.Vehicle.DesignationEn = "asdfasdfa";
 re.Vehicle.DesignationFr = "1qweqweqweq";

 ctx.SaveChanges();

Context:

this.ChangeTracker.DetectChanges();

var objectContext = ((IObjectContextAdapter)this).ObjectContext;

var entries = objectContext
   .ObjectStateManager
   .GetObjectStateEntries(EntityState.Modified | EntityState.Added | EntityState.Deleted);

foreach (var entry in entries)
{
    //you can see Vehicle changes here.
}

You probably won't face this problem if the LazyLoading is disabled.

Sources:

Entity Framework won't detect changes of navigation properties

Entity Framework 4.1+ many-to-many relationships change tracking

Community
  • 1
  • 1
Fabio
  • 11,892
  • 1
  • 25
  • 41
  • With the solution you suggested `var entries = ChangeTracker.Entries().Where(...)` if I modify `BudgetNumber` which is a string I get an entry BUT if I modify the `Vehicle` which is a relationship I don't get any entries. Any idea why? Because I really need to log any user modifications (especially the Vehicle). Thanks. – Bronzato Aug 18 '15 at 21:15
  • I'll take a look when I get home – Fabio Aug 18 '15 at 21:17
  • No sorry, probably I was not clear. When I said I modified the `Vehicle`, I mean selected another Vehicle. Not changing it. Let me explain you: I have a list of vehicles (Honda, Hyundai, ...) and I add (a reference to) it on my `Request`. Each time I (remove the old one and) add a `Vehicle` on my 'Request' and run your code, I didn't get anything. But with my own code (see my answer) I got relationship changes (in this case this is an add). But with my code I don't know how to manage the relationship data to retrieve the 2 (tracked) entities (each part of the relationship). Thanks. – Bronzato Aug 19 '15 at 06:40
  • By the way I'll take a look at your second link (Entity Framework 4.1+ many-to-many relationships change tracking) maybe this can be useful. – Bronzato Aug 19 '15 at 06:44
  • The second link you provided points me to the right direction. Many thanks. – Bronzato Aug 19 '15 at 19:34