Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
154 views
in Technique[技术] by (71.8m points)

c# - Get entity navigation properties after insert

I have the following 2 classes:

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; }
}

With this I have all the obvious necessary stuff like a DbContext and mappings.

Now let's say I create a Reward entity and insert it like this:

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

I obviously have a campaign with Id 1 so the FK constraint is happy. After this insert, my reward entity has it's new Identity Id set. Now the problem is that reward is still just the Reward entity I created. And with this, the reward.Campaign property is null. It seems like EF is keeping the inserted entities in memory, and when I then do a .SingleOrDefault(a => a.Id == reward.Id) it simply returns the entity in memory, and not a new proxy. This is probably a good thing.

So the question is: How does one access or load the navigation properties after an insert or get a new proxy that has the navigation properties as proxies as well.

Am I perhaps inserting in the wrong way?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If I understand you correctly, you're trying to eagerly load a complex property after establishing a relationship via a foreign key property.

SaveChanges() does not do anything in the way of loading complex properties. At most, it is going to set your primary key property if you're adding new objects.

Your line reward = context.Set<Reward>().SingleOrDefault(a => a.Id == reward.Id); also does nothing in the way of loading Campaign because your reward object is not attached to the context. You need to explicitly tell EF to load that complex object or attach it then let lazy loading work its magic.

So, after you context.SaveChanges(); you have three options for loading reward.Campaign:

  1. Attach() reward to the context so that Campaign can be lazily loaded (loaded when accessed)

     context.Rewards.Attach(reward);
    

    Note: You will only be able to lazy load reward.Campaign within the context's scope so if you're not going to access any properties within the context lifespan, use option 2 or 3.

  2. Manually Load() the Campaign property

     context.Entry(reward).Reference(c => c.Campaign).Load();
    

    Or if Campaign was a collection, for example Campaigns:

     context.Entry(reward).Collection(c => c.Campaigns).Load();
    
  3. Manually Include() the Campaign property

     reward = context.Rewards.Include("Campaigns")
         .SingleOrDefault(r => r.Id == reward.Id);
    

    Although, I'd suggest Load since you already have reward in memory.

Check out the Loading Related Objects Section on this msdn doc for more information.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...