插入/添加后强制重新加载实体框架中的实体

Sea*_*ean 1 c# entity-framework

我有一个Project实体,定义为:

public class Project
{
    [Key]
    public Guid ProjectId { get; set; }
    //...
    [Required, ForeignKey("User")]
    public Guid UserId { get; set; }
    public virtual User User { get; set; }    
}
Run Code Online (Sandbox Code Playgroud)

在我的控制器中,我有:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

问题是当控制器返回新插入的项目时,虚拟字段User将为空,因为它尚未加载/填充用户数据。

在线路上,// issue:我尝试了这两行:

if (isNew)
{
    // try one of these two lines:
    DbContext.Entry(project).Reload();
    project = DbContext.Projects.Find(project.ProjectId);
}
Run Code Online (Sandbox Code Playgroud)

但两者都没有效果:我认为使用Find实际上并没有返回到数据库,因为实体已经存在于上下文中,所以它只是返回那个。但是我本以为重新加载会强制完全重新加载具有 FK 关系的项目,但事实并非如此。

我可以做这样的事情:

if (isNew)
{
    project.User = DbContext.Users.Find(project.UserId);
}
Run Code Online (Sandbox Code Playgroud)

但这看起来并不像我想要的那么干净:我必须为我返回的每个 FK 都这样做。

处理这个问题的最佳方法是什么?

Jcl*_*Jcl 5

您可以先分离它,这应该会强制重新加载发现:

DbContext.Entry(project).State = EntityState.Detached;
project = DbContext.Projects.Find(project.ProjectId);
Run Code Online (Sandbox Code Playgroud)

如果这不起作用,您可以使用 来分离它ObjectContext,但这可能会停止在未来版本的 EF 上工作(DbContext不使用的地方ObjectContext):

((IObjectContextAdapter)DbContext).ObjectContext.Detach(project);
Run Code Online (Sandbox Code Playgroud)