Reputation: 15144
I have a Project
entity, defined as:
public class Project
{
[Key]
public Guid ProjectId { get; set; }
//...
[Required, ForeignKey("User")]
public Guid UserId { get; set; }
public virtual User User { get; set; }
}
In my controller, I have:
// insert
public IHttpActionResult Post([FromBody] ProjectDTO projectDTO)
{
return Save(projectDTO);
}
// update
public IHttpActionResult Post(Guid id, [FromBody] ProjectDTO projectDTO)
{
return Save(projectDTO);
}
private IHttpActionResult Save(ProjectDTO projectDTO)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
var isNew = projectDTO.ProjectId == Guid.Empty;
Project project;
if (isNew)
{
project = new Project();
var user = UserManager.FindByName(User.Identity.Name);
projectDTO.UserId = new Guid(user.UserId.ToString());
DbContext.Entry(project).State = EntityState.Added;
}
else
{
project= DbContext.Projects.Find(projectDTO.ProjectId);
if (project == null) return NotFound();
DbContext.Entry(project).State = EntityState.Modified;
}
// set fields from DTO to User...
DbContext.SaveChanges();
// issue:
return Ok(project);
}
The issue is that when a newly inserted project is returned by the controller, the virtual field User
will be null because it hasn't been loaded/populated with the User data.
On the line // issue:
I tried both of these lines:
if (isNew)
{
// try one of these two lines:
DbContext.Entry(project).Reload();
project = DbContext.Projects.Find(project.ProjectId);
}
But both had no effect: I assume using the Find
is not actually going back to the database because the entity already exists in the context, so it just returns that. But I would have thought the reload would have forced a full reload of the project with FK relationships, but it didn't.
I could do something like this:
if (isNew)
{
project.User = DbContext.Users.Find(project.UserId);
}
But that doesn't look as clean as I'd like: I'd have to do it for each FK that I'm returning.
What's the best way to handle this?
Upvotes: 2
Views: 7054
Reputation: 28272
You can detach it first, this should force the reloading upong finding:
DbContext.Entry(project).State = EntityState.Detached;
project = DbContext.Projects.Find(project.ProjectId);
If that doesn't work, you could detach it using the ObjectContext
instead, but that will probably stop working on future versions of EF (where DbContext
doesn't use ObjectContext
):
((IObjectContextAdapter)DbContext).ObjectContext.Detach(project);
Upvotes: 6