15

ナビゲーション プロパティの変更の検出に問題があります。

私のテストモデルは次のようになります。

public class Person
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual Address Address { get; set; }
}

public class Address
{
    public int Id { get; set; }

    public string Name { get; set; }
}

Name プロパティと Address プロパティの両方が割り当てられた Person 型のオブジェクトを作成して保存しました。私の問題は、Person オブジェクトをデータベースから取得し、Address プロパティを (たとえば Null に) 変更すると、ef が変更を検出しないことです! 私のコードはこれです:

using (var ctx = new EFContext())
{
    Person p = ctx.People.First();
    //p.Address IS NOT NULL!
    p.Address = null;
    var entry = ctx.Entry(p);
}

entry.State 変更されていないのはなぜですか?

編集: SaveChanges を呼び出すと、レコードが正しく保存されます (アドレスが null になります)。

編集 2:ビリーが提案したように外部キー プロパティを作成しました。Visual Studio で Person オブジェクトを調べると、State は Modified です。オブジェクトの値を調べるデバッガで停止しない場合、State は Unchanged です!

編集 3: ctx.People.Include(x => x.Address).First(); を使用して Person オブジェクトをロードする 問題を解決します。Include の呼び出しを回避し、AddressId の代わりに Address プロパティを変更し続ける方法はありますか?

4

3 に答える 3

5

住所ナビを含める必要があります。小道具。そうしないと、EF は保存時に変更を考慮しません。

using (var ctx = new EFContext())
{
    Person p = ctx.People.Include(x => x.Address).First();
    //p.Address IS NOT NULL!
    p.Address = null;
    var entry = ctx.Entry(p);
}

モデルで外部キーを使用することもできます。これは非常に気に入っています。

public class Person
{
    public int Id { get; set; }

    public string Name { get; set; }

    public virtual Address Address { get; set; }

    public int? AddressId {get; set;}
}

...

using (var ctx = new EFContext())
{
    Person p = ctx.People.First();
    p.AddressId = null;
    var entry = ctx.Entry(p);
}
于 2012-07-26T13:33:07.147 に答える
2

私のアプリケーションでは、リロードが要求されるか、ユーザーがアイテム/ビューを離れる前に、保存されていない変更がないことを確認するためにいくつかのチェックを実行します。

これは基本的に現在受け入れられている回答から外れていますが、実装を提供し、ピックアップできる関係が変わるContext.ChangeTracker.DetectChanges()前に電話する必要があることに注意を向けたいと思いました! ObjectContext.ObjectStateManager私はこれをデバッグするのにかなりの時間を費やしました。

_EagleContext.ChangeTracker.DetectChanges();

var objectContext = ((IObjectContextAdapter)_EagleContext).ObjectContext;
var changedEntities = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified);

if (_EagleContext.ChangeTracker.Entries().Any(e => e.State == EntityState.Modified)
    || changedEntities.Count() != 0)
{
    var dialogResult = MessageBox.Show("There are changes to save, are you sure you want to reload?", "Warning", MessageBoxButton.YesNo);
    if (dialogResult == MessageBoxResult.No)
    {
        return;
    }
}

// Continue with reloading...
于 2013-08-19T00:33:00.940 に答える