ISortable インターフェイスを実装するクラスがいくつかあります。
public interface ISortable
{
int Id { get; set; }
int? Idx { get; set; }
}
私の DbContext クラスには、ISortable を実装するエンティティに対していくつかの追加処理を行う update メソッドがあります。
public void UpdateSingle<T>(T item) where T : class
{
// If entity is Sortable, update the indexes of the records between the new and the old index of the updated entity
var sortable = item as ISortable;
if (sortable != null)
{
Detach(item); // need to detach the entity from the context in order to retrieve the old values from DB
var oldItem = Find<T>(sortable.Id) as ISortable;
if (oldItem != null && sortable.Idx != oldItem.Idx)
{
var entities = FindAll<T>().ToList().Cast<ISortable>();
var oldIdx = oldItem.Idx;
var newIdx = sortable.Idx;
if (newIdx > oldIdx)
{
var toUpdate = entities.Where(a => a.Idx <= newIdx && a.Idx > oldIdx).Select(a => a);
foreach (var toUpdateEntity in toUpdate)
{
toUpdateEntity.Idx = toUpdateEntity.Idx - 1;
}
}
else
{
var toUpdate = entities.Where(a => a.Idx >= newIdx && a.Idx < oldIdx).Select(a => a);
foreach (var toUpdateEntity in toUpdate)
{
toUpdateEntity.Idx = toUpdateEntity.Idx + 1;
}
}
}
Detach(oldItem);
Attach(item); // re-attach to enable saving
}
Entry(item).State = EntityState.Modified;
Commit();
}
私が疑問に思っているのは、次の行です。
var entities = FindAll<T>().ToList().Cast<ISortable>();
エンティティを ISortable にキャストするには、LINQ to SQL 式をリストに変換する必要があります。そして、これを実行するために ISortable にキャストする必要があります Where:
var toUpdate = entities.Where(a => a.Idx <= newIdx && a.Idx > oldIdx).Select(a => a);
Idx 属性は、インターフェースによって公開されます。
問題は、FindAll() で ToList() を呼び出すと、テーブル全体がメモリに読み込まれることです。
最初にテーブル全体をロードせず、汎用実装を失うことなく Where を実行する方法はありますか?
ここでの考え方は、「並べ替え可能な」すべてのエンティティの更新時に共通のアクションを実行したいということです。これが機能するには、さまざまなクラスを処理するために更新メソッドを汎用にする必要がありますが、必要なフィールドを公開するためのインターフェイスが必要です...これを行うためのより良い方法がある場合 (おそらくある)、お知らせください。 . :-)