26

I have a entity framework database first project. here is a extraction of the model:

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

I have a problem with setting the navigation item ResponsibleUser of the class LedProject. When I set the ResponsibleUser to a another user and afterwards save the changes of the DBContext, the changes are stored in the database.

But, when I want to delete the current ResponsibleUser of an LedProject, by setting the navigation property to null. The changes are not stored in the database.

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();

Is there any trick for deleting navigation properties?

4

8 に答える 8

49

問題は、ナビゲーション プロパティの遅延読み込みにあります。値は最初に null に設定され、その後データベースからロードされるようです。したがって、目的の値 (私の場合はnull ) は、データベースに現在格納されている値によって上書きされます。

LedProject project = db.LedProject
    .Include("ResponsibleUser")
    .Where(p => p.ProjectId == projectId)
    .FirstOrDefault();

これにより、プロジェクトが読み込まれるときにResponsibleUserが読み込まれます。これでようやく問題が解決しました!

于 2012-10-11T07:42:23.650 に答える
5

boindiilが言ったように、問題は遅延読み込みにあります。ただし、プロパティを null にする場合にのみプロパティをロードする必要があるため、Entity Framework 機構はプロパティが変更されたことを認識します。コードは次のようになります。

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();

db.ChangeTracker を使用して負荷なしで保存を強制する方法があるはずだと考え続けていますが、まだ見つけていません (そして、私が試したいくつかのことは本当にハックに思えました)。

于 2014-12-03T12:46:53.730 に答える
4

ナビゲーション プロパティを熱心に読み込む必要がFind()なく、ハックを行う必要がなく EF を引き続き使用できるようにするための最良の方法を考え出しました。

タイプがナビゲーション プロパティの ID タイプ (通常はユーザーの場合は文字列) であるナビゲーション プロパティと一緒にプリミティブ ID を使用します。

public partial class LedProject
{
    public string ResponsibleUserId { get; set; }
    public virtual User ResponsibleUser { get; set; }
}

レコードを作成する場所でナビゲーション プロパティを使用して文字列を更新し、関係を削除する場合はledProject.ResponsibleUserId = null.

最後にナビゲーション プロパティの名前 + id 以外の名前を ID に付ける場合は、注釈または流暢な API を使用してマップする必要があると思います。

詳細はこちら:どのシナリオでエンティティ フレームワークに外部キーとナビゲーション プロパティが必要ですか

于 2016-08-06T14:37:15.957 に答える
3

Entity Framework 5.0 以降:

db.Entry(project).Reference(p => p.ResponsibleUser).CurrentValue = null;

https://msdn.microsoft.com/en-us/data/jj713564.aspx

于 2016-09-30T16:45:00.880 に答える