1

EF 4.1、POCO:データの更新を高速化するためにAutoDetectChangesConfiguration.AutoDetectChangesEnabled = false )をオフにしました。次に、エンティティの状態をEntityState.Modifiedに変更して、追加またはアタッチを実行します。これにより、データベースで更新されていない他のオブジェクトへの参照が発生します。ただし、すべてのスカラープロパティは正常に更新されます。

プロファイラーが示すEFは、すべてのスカラープロパティに対してSQL更新操作を生成しますが、参照型に対しては生成しませんが、コードでその値を実際に変更しました。この問題は、私のモデルのすべてのタイプのエンティティで再現されました。

操作を追加するか、 EntityStateでアタッチします。両方とも正常に機能します。AutoDetectChangesをオンに戻すと、更新されたレコードでも期待どおりにすべてが正常に機能します。

何が悪いのか理解するのを手伝ってください。EFのDetectChangesに関する優れた包括的なドキュメントが見つかりません。

アップデート

問題を再現するために、コードの例をいくつか示すように求められました。ドメイン:

public class Client
{
    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 virtual string City { get; set; }
}

DataContext:

public class DataContext : DbContext
{

    public DbSet<Client> Clients { get; set; }
    public DbSet<Address> Address { get; set; }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
    base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Client>().HasOptional(c => c.Address);
    }
}

1つのレコードをClintテーブルに追加し、もう1つをアドレスに追加します。クライアントをアドレスにポイントします。次に、次のコードを実行します。

using (var cntx = new DataContext())
{
    cntx.Configuration.AutoDetectChangesEnabled = false; // Reason of problem
    var client = cntx.Clients.First();
    client.Name = "Anna"; // This property will be updated
    client.Address = null;  // This property will not be updated
    cntx.Clients.Attach(client);
    cntx.Entry(client).State = EntityState.Modified;
    cntx.SaveChanges();
}

このコードは、次のようなSQLスクリプトを生成します。

update [dbo].[Clients] set [Name] = 'Anna'
where ([Id] = 1)

AutoDetectChangesEnabledをtrueに設定し、コードを再実行します。今回はすべて問題ありません。

update [dbo].[Clients]
set [Name] = 'Anna', [Address_Id] = null
where (([Id] = 1) and [Address_Id]=1)

Addressの値を特定の値からnullに変更するか、特定の値に戻すか、または1つの具象値を他の具象値に戻すかは問題ではないことに注意してください。AutoDetectChanges= falseの間、変更は追跡されません。EFバグのようです。

4

2 に答える 2

2

MSDNの変更追跡を参照してください

于 2011-08-16T20:54:54.370 に答える
2

AutoDetectChangesEnabled=falseでも機能するReferenceプロパティ値を設定する方法を見つけました。

cntx.Entry(client).Reference(c => c.Address).CurrentValue = null;

しかし、私は間違いなくそれが好きではありません。1)コードが見苦しい。2)それを機能させるには、コンテキストにアクセスできる必要がありますが、私の場合はそうではありません。このプロパティは、DbContextにのみアクセスできるリポジトリの外部に設定する必要があります。プロパティ値が変更されたことをEFに知らせる他の簡単な方法はありますか?

更新:わかりました。より簡単な回避策を見つけました。cntx.SaveChanges()を実行する前にcntx.ChangeTracker.DetectChanges()を実行するだけです。EFが正しいSQL更新スクリプトを生成するのに役立ちます

于 2011-08-17T22:36:29.247 に答える