0

I'll try to update my entity after setting a new FOREIGN KEY value.

My (simplified) entities are:

public class FirstEntity
{
    public Guid Id { get; set; }
    public Guid SecondEntityId {get; set;} // <-- this is the FK        
    public virtual SecondEntity SecondEntity { get; set; } // <-- this is the navigation property
}

public class SecondEntity 
{
    public Guid Id { get; set;}     
    public virtual ICollection<FirstEntity> FirstEntity { get; set; }
}

At some point in my code I want to change the reference for an object of type FirstEntity by setting the FK-value to a new value.

var theFirstEntity = DbContext.FirstEntity.Single(f => f.Id == Guid.Parse("5e27bfd3-d65b-4164-a0e4-93623e1b0de0"));
// at this point theFirstEntity.SecondEntityId is 'e06f8909-98f9-4dc6-92ec-49d9a6aac831'

theFirstEntity.SecondEntityId = Guid.Parse("C5AB5CBA-5CD8-40B7-ABFB-C22F17646D44"); // <-- existing Id from database
// now theFirstEntity.SecondEntityId is 'C5AB5CBA-5CD8-40B7-ABFB-C22F17646D44' 
// but the reference theFirstEntity.SecondEntity is still pointing the 'old' entity with id 'e06f8909-98f9-4dc6-92ec-49d9a6aac831' 
// but it should have id 'C5AB5CBA-5CD8-40B7-ABFB-C22F17646D44

Now I try to load the new reference explicitly using

DbContext.Entry(FirstEntity).Reference(t => t.SecondEntity).Load();

as found here.

But FirstEntity.SecondEntity stays the same System.Data.Entity.DynamicProxies.SecondEntity_XYZ as it was before. On the other side, when looking at DbContext.Entry(FirstEntity).Reference(t => t.SecondEntity).Query() and the values of the Parameters property, the query seems to be correct by looking after Id = 'C5AB5CBA-5CD8-40B7-ABFB-C22F17646D44'.

Instead it should containt the correct entity of type SecondEntity with the Id 'C5AB5CBA-5CD8-40B7-ABFB-C22F17646D44' and not the 'old' value.

KingKerosin
  • 3,639
  • 4
  • 38
  • 77
  • Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Complete, and Verifiable example. – TomTom Apr 26 '16 at 08:31
  • Desired behavior is to have the correct property-value set. The problem is, that the property stays untouched after explicitly loading it. Code to reproduce has been added. Hope this is okay now – KingKerosin Apr 26 '16 at 08:46
  • @KingKerosin, sorry I don't know much about your main issue but anyway you shouldn't use Guid as a primary key (in fact as a clustered index), this is a bad practice using SQL Server: http://stackoverflow.com/questions/11938044/what-are-the-best-practices-for-using-a-guid-as-a-primary-key-specifically-rega – Thomas Apr 26 '16 at 09:36
  • @Thomas Even if I can't change this and it does not help me with my current issue, thanks for the link anyway. Indeed it's very interesting – KingKerosin Apr 26 '16 at 09:42

1 Answers1

0

You need to SaveChanges and then explicitly load.

theFirstEntity = myDbContext.FirstEntity.Single(f => f.Id == Guid.Parse("5e27bfd3-d65b-4164-a0e4-93623e1b0de0"));
theFirstEntity.SecondEntityId = Guid.Parse("C5AB5CBA-5CD8-40B7-ABFB-C22F17646D44");

myDbContext.SaveChanges();

DbContext.Entry(theFirstEntity).Reference(t => t.SecondEntity).Load();

But in this case it would be more convenient to just assign a new and already loaded SecondEntity value to the FirstEntity:

var f = myDbContext.Set<FirstEntity>().Include(p => p.SecondEntity)
    .Single(x => x.Id == Guid.Parse("5e27bfd3-d65b-4164-a0e4-93623e1b0de0"));

var s = myDbContext.Set<SecondEntity>()
    .Single(x => x.Id == Guid.Parse("C5AB5CBA-5CD8-40B7-ABFB-C22F17646D44"));

f.SecondEntity = s;

myDbContext.SaveChanges();
Vojtěch Dohnal
  • 7,867
  • 3
  • 43
  • 105
  • As the example/question is only an example, in my real application it's inside an even bigger framework. So `SaveChanges()` would always hit the underlying database. I guess there is no other way to achieve what I want? Playing around with EntityStates or something like this? – KingKerosin Apr 26 '16 at 08:57
  • If you want to "cheat" EF to believing that the actual related entity is something else then it is in the database and load it into EF object graph, it is not a good idea. Create different object graph yourself - like ViewModel, custom class etc. – Vojtěch Dohnal Apr 26 '16 at 09:01
  • It doesn't feel like "cheating" when I want to explicity load a reference after it has been changed, no? Maybe there is a completely different way to go by refreshing the context or the entity after the change? – KingKerosin Apr 26 '16 at 09:05
  • @KingKerosin Then do not explicitly load, but assign the SecondEntity value to the FirstEntity. – Vojtěch Dohnal Apr 26 '16 at 09:22