8

一般的な問題と思われる問題が発生しました。データベースの値を更新していますが、EFはオブジェクトの元のメモリ内コピーを使用しており、これらの変更された値は表示されたデータに反映されません。これがなぜなのかは理解できますが、それを回避する方法がわかりません。

最も一般的な解決策は、MergeOptions.NoTracking変更の追跡を完全にオフにし(またはAsNoTracking()クエリ時に拡張メソッドを使用し)、オブジェクトにアクセスするたびに強制的に更新するように設定することです。これは私の目的には問題ありません。

他のリポジトリから継承する汎用ベースリポジトリがあります。

public abstract class RepositoryBase<T> where T : class
{
    private readonly IDbSet<T> _dbset;
    private readonly IUnitOfWork _unitOfWork;

    protected RepositoryBase(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
        _dbset = _unitOfWork.Database.Set<T>();
    }

    public virtual IQueryable<T> All()
    {
        return _dbset;
    }

    // Some other IQueryable methods here (Query, GetByProductCode etc)

    public virtual T Get(long id)
    {
        return _dbset.Find(id);
    }
}    

そしてDbContextこのように:

public class Db : DbContext
{
    private IDbSet<Product> _products;

    public IDbSet<Product> Products
    {
        get { return _products ?? (_products = DbSet<Product>()); }
    }

    public virtual IDbSet<T> DbSet<T>() where T : class
    {
        return Set<T>();
    }

    public virtual void Commit()
    {
        base.SaveChanges();
    }
}

All()したがって、リポジトリのメソッドを変更すると、次のようになります。

public virtual IQueryable<T> All()
{
    return _dbset.AsNoTracking();
}

希望する結果が得られました。製品を表示しているページが更新されると、データベースの更新が反映されます。Get()ただし、この拡張メソッドはでのみ機能するため、メソッドでこれを行うことはできませんIQueryable

変更の追跡は必要ないので、理想的にはこれをレベルでオフにしたいのDbContextですが、これを行うための明確な方法はないようであり、主題に関するドキュメントはほとんどありません(誰かが指摘できない限り)私を誰かに?お願いします!)

DbContextこれらの構成オプションを無効にして、コンストラクターをに追加してみました。

public Db()
{
    base.Configuration.ProxyCreationEnabled = false;
    base.Configuration.AutoDetectChangesEnabled = false;
}

しかし、私は彼らが実際に何をしているのかを推測しているだけであり(私はソースコードを見てそれらを見つけただけです)、とにかく効果がないようです。

どんな助けでも大歓迎です。より多くの情報/コードが役立つ場合は、私に知らせてください。

4

1 に答える 1

6

メソッドを使用しないたびにコンテキストに新しいデータを取得させる場合FindFindメソッドは常に最初に内部ストレージを照会します。代わりにこれを使用してください:

public virtual T Get(long id)
{
    return All().SingleOrDefault(e => e.Id == id);
}

しかし、私はあなたがこれを何が必要なのか分かりませんか?どういう意味:

製品を表示しているページが更新されると、データベースの更新が反映されます

コンテキストは作業の単位です。作業の単位として使用する必要があります。WebアプリケーションまたはWebサービスでは、リクエストごとに新しいコンテキストインスタンスを作成することを意味します。winforms / wpfアプリケーションでは、論理ブロックごと(プレゼンターごとなど)にコンテキストを使用することを意味します。そのため、これは非常に特定のシナリオでのみ必要ですが、グローバルに必要です。あなたの説明は、リクエスト間でコンテキストを再利用しているようですが、これは完全に悪い解決策です。各リクエストのコンテキストを再作成する際にパフォーマンスコストは発生しません。

于 2011-03-31T16:12:59.803 に答える