实体框架将导航属性设置为null

boi*_*iil 21 c# entity-framework

我有一个实体框架数据库第一个项目.这是模型的提取:

public partial class LedProject
{
    public LedProject()
    {
        this.References = new HashSet<LedProjectReference>();
        this.Results = new HashSet<LedProjectResult>();
        this.History = new HashSet<LedProjectHistory>();
    }

    public string Identifier { get; set; }
    public string Name { get; set; }
    public Nullable<System.DateTime> CompletionDate { get; set; }
    public System.DateTime CreationDate { get; set; }
    public System.Guid ProjectId { get; set; }
    public string Comment { get; set; }

    public virtual User ContactUser { get; set; }
    public virtual User CreationUser { get; set; }
    public virtual Customer Customer { get; set; }
    public virtual LedProjectAccounting Accounting { get; set; }
    public virtual LedProjectState State { get; set; }
    public virtual ICollection<LedProjectReference> References { get; set; }
    public virtual ICollection<LedProjectResult> Results { get; set; }
    public virtual User ResponsibleUser { get; set; }
    public virtual ICollection<LedProjectHistory> History { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
public partial class User
{
    public System.Guid UserId { get; set; }
    public string LoginName { get; set; }
    public System.DateTime CreationDate { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我在设置类的导航项ResponsibleUser时遇到问题LedProject.当我将其设置ResponsibleUser为另一个用户并随后保存DBContext的更改时,更改将存储在数据库中.

但是,当我想删除当前ResponsibleUser的an时LedProject,通过将navigation属性设置为null.更改不存储在数据库中.

LedProject project = db.LedProject.Find(projectId);
project.Name = string.IsNullOrEmpty(name) ? null : name;
...
project.ResponsibleUser = responsibleUser == null ? null : db.User.Find(responsibleUser.UserId);
...
db.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

有删除导航属性的技巧吗?

boi*_*iil 40

问题在于导航属性的延迟加载.似乎该值首先设置为null,然后从数据库加载.因此,期望的值(在我的情况下为null)被数据库中当前存储的值覆盖.

LedProject project = db.LedProject
    .Include("ResponsibleUser")
    .Where(p => p.ProjectId == projectId)
    .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

这会在加载项目时加载ResponsibleUser.这终于解决了我的问题!

  • 你刚刚把我从准备中拯救出来 - 谢谢! (5认同)
  • 没有急切加载导航属性有没有办法解决这个问题? (2认同)
  • 这是非常糟糕的。我不得不停止使用`Find()`,而改用`Where()`。一直在打我自己的脸,直到我发现这个,谢谢。 (2认同)

mhe*_*man 5

就像boindiil所说的,问题在于延迟加载。但是,只有在想要将其置空时才需要加载该属性,以便实体框架机制知道它已更改。代码可能如下所示:

responsibleUser = responsibleUser == null ? null : db.User.Find(responsibleUser.UserId);
if (responsibleUser == null)
{
    // load the value to assure setting it to null will cause a change
    var dummy = project.ResponsibleUser; 
}

project.ResponsibleUser = responsibleUser;
...
db.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

我一直在想应该有一种方法可以使用 db.ChangeTracker 在没有负载的情况下强制保存,但我还没有找到它(我尝试过的几件事看起来真的很糟糕)。