リポジトリパターンを介してEntityFrameworkを使用していますが、重大で驚くべきパフォーマンスの問題があります。私はプロファイリングを行ったので、何が起こるかについてかなり良い考えを持っています、私はそれについて何をすべきかわからないだけです。
これが私のコードの本質です(簡略化):
var employee = Repositories.Employees.FirstOrDefault(s => s.EmployeeId == employeeId);
employee.CompanyId = null;
Repositories.Commit();
真ん中の線(employee.CompanyId = null
)は、完了するまでに驚くほどの時間(約30秒)かかります。時間はコミット行に費やされません。
プロファイリングを通じて、自動生成されたEFコードのこの部分を実行する理由を見つけました。
if (previousValue != null && previousValue.**Employees**.Contains(this))
{
previousValue.Employees.Remove(this);
}
それは本当に私を助けませんが、それは問題がEFにあることを確認します。どうしたらいいのか本当に知りたいです。他の方法(ストアドプロシージャ)で列を更新できますが、実際にはどこでもEFを使用したいと思います。
EF設定を簡単に編集できないので、これを含まない提案をしたいと思います。
更新 データベースに対してSQLを直接実行し、コンテキストからオブジェクトを更新して、EFがこの変更をすぐに検出するようにすることで、問題を解決しました。
public void SetCompanyNull(Guid employeeId)
{
_ctx.ExecuteStoreCommand("UPDATE Employee SET CompanyId = NULL WHERE EmployeeId = N'" + employeeId + "'");
_ctx.Refresh(RefreshMode.StoreWins, _ctx.Employees.FirstOrDefault(s => s.EmployeeId == employeeId));
}
アップデート2 また、遅延読み込みを一時的に無効にすることで問題を解決しました。
var lazyLoadDisabled = false;
if (_ctx.ContextOptions.LazyLoadingEnabled)
{
_ctx.ContextOptions.LazyLoadingEnabled = false;
lazyLoadDisabled = true;
}
this.GetEmployeeById(employeeId).CompanyId = null;
this.SaveChanges();
if (lazyLoadDisabled)
{
_ctx.ContextOptions.LazyLoadingEnabled = true;
}
遅延読み込みを無効にすると、なぜこれほど高速になるのか(そして、これがどのような副作用をもたらす可能性があるのか)、私は本当に興味があります。