Ho le seguenti 2 classi:
public class Reward
{
public int Id { get; set; }
public int CampaignId { get; set;
public virtual Campaign Campaign { get; set; }
}
public class Campaign
{
public int Id { get; set; }
public virtual ICollection<Reward> Rewards { get; set; }
}
Con questo ho tutte le cose ovvie necessarie come un DbContext e mappature.
Ora diciamo che creo un'entità Reward e la inserisco in questo modo:
var reward = new Reward { CampaignId = 1 };
context.Set<Reward>().Add(reward);
context.SaveChanges();
reward = context.Set<Reward>().SingleOrDefault(a => a.Id == reward.Id);
//reward.Campaign is null
Ovviamente ho una campagna con l'Id 1, quindi il vincolo FK è felice. Dopo questo inserimento, la mia entità di ricompensa ha il suo nuovo ID di identità impostato. Ora il problema è che la ricompensa è ancora solo l'entità Premio che ho creato. E con questo, la proprietà reward.Campaign è nullo. Sembra che EF stia mantenendo le entità inserite in memoria, e quando poi faccio un .SingleOrDefault (a => a.Id == reward.Id) restituisce semplicemente l'entità in memoria e non un nuovo proxy. Questa è probabilmente una buona cosa.
Quindi la domanda è: come si accede o si caricano le proprietà di navigazione dopo un inserimento o si ottiene un nuovo proxy che ha anche le proprietà di navigazione come proxy.
Sto forse inserendo nel modo sbagliato?
Se ti capisco correttamente, stai provando a caricare avidamente una proprietà complessa dopo aver stabilito una relazione tramite una proprietà di chiave esterna.
SaveChanges()
non fa nulla nel modo di caricare proprietà complesse. Al massimo, imposterà la proprietà della chiave primaria se si aggiungono nuovi oggetti.
La tua reward = context.Set<Reward>().SingleOrDefault(a => a.Id == reward.Id);
riga reward = context.Set<Reward>().SingleOrDefault(a => a.Id == reward.Id);
inoltre non fa nulla nel caricamento di Campaign
perché il tuo oggetto premio non è collegato al contesto. Devi dire esplicitamente a EF di caricare quell'oggetto complesso o collegarlo, quindi lasciare che il caricamento lazy funzioni la sua magia.
Quindi, dopo aver context.SaveChanges();
hai tre opzioni per caricare la reward.Campaign
. reward.Campaign
:
Attach()
ricompensa al contesto in modo che Campaign
possa essere caricato pigramente (caricato quando si accede)
context.Rewards.Attach(reward);
Nota: sarai in grado di caricare pigro reward.Campaign
. reward.Campaign
nell'ambito del contesto, quindi se non reward.Campaign
a nessuna proprietà all'interno della durata del contesto, utilizza l'opzione 2 o 3.
Load()
manualmente Load()
la proprietà Campaign
context.Entry(reward).Reference(c => c.Campaign).Load();
Include()
manualmente Include()
la proprietà Campaign
reward = context.Rewards.Include("Campaigns")
.SingleOrDefault(r => r.Id == reward.Id);
Anche se, suggerirei Load
perché hai già una reward
in memoria.
Consulta la sezione Caricamento degli oggetti correlati su questo documento msdn per ulteriori informazioni.
Mentre stai creando il tuo oggetto reward
come new Reward()
, EF non ha un proxy. Invece, crearlo usando DbSet.Create in questo modo:
var reward = context.Set<Reward>().Create();
reward.CampaignId = 5;
context.SaveChanges();
Quindi collegalo al tuo DbSet:
context.Rewards.Attach(reward);
Infine, ora puoi utilizzare il caricamento lazy per ottenere entità correlate:
var campaign = reward.Campaign;