1

IsSoftDeletedこのDbSetからアイテムをフィルタリングするにはどうすればよいですか?

var type = GetTypeFromString("Whatever");
var whatevers = Set(type);

方法

public dynamic Set(Type type)
{
    var set = dbContext.Set(type);
    return set;
}

モデル

public class Whatever : BaseEntity
{
    public virtual string Name { get; set; }
}
public class BaseEntity
{
   public virtual int Id { get; set; }
   public virtual bool? IsSoftDeleted { get; set; }
}

編集:表示するのを忘れたからWhatever派生BaseEntity

4

2 に答える 2

4

あなたのWhateverクラスにはIsSoftDeletedプロパティがないため、フィルタリングするものはありません。私は、BaseEntity から派生したものは何でもあると仮定します。

主な問題は、IQueryable<T>.Where が実際には存在しないことです。これは拡張メソッドであり、拡張メソッドは動的な型では適切に機能しません。型が IQueryable<T> を実装していることをコンパイラが確認できる場合は、var.Where(...) と入力して、コンパイラにそれを System.Linq.Queryable.Where(var, ...) に解決させることができます。この例では型が動的であるため、コンパイラはそれが IQueryable を実装していることを認識せず、Where を呼び出そうとするとエラーを報告します。

DbSet を IQueryable<BaseEntity> にキャストし (Type が基本クラスとして BaseEntity を持っている限り)、そのフィルターを呼び出すことができます。実際に動的型機能を使用していますか? そうでない場合は、カスタム Set 関数を削除して、既定の DbContext.Set 関数を使用することも検討できます。

var query = (from e in (IQueryable<BaseEntity>)dbContext.Set(type)
             where e.IsSoftDeleted != true
             select e);

注: これはdbContext.Set(type).Cast<BaseEntity>(): の使用と同じではありません: DbSet<BaseEntity> と DbSet<Whatever> には互換性がないため、これは機能しません。これを行うことができるのは、IQueryable および「out」型引数を持つ他のインターフェイスのみです。

于 2011-12-06T23:06:43.807 に答える
3

問題はSet(Type type)、非ジェネリックを返すことDbSetです。フィルターを適用するには、それをジェネリックにキャストする必要がありますIQueryable<T>

var set = ((IQueryable<BaseEntity>)dbContext.Set(type))
              .Where(be => be.IsSoftDeleted.HasValue && !be.IsSoftDeleted.Value);

これは、またはそれ自体typeから派生した場合にのみ機能します。それ以外の場合は、実行時例外が発生します。BaseEntityBaseEntity

結果setのタイプIQueryable<BaseEntity>は であるため、問題は、この結果がどれほど役立つか、および のような派生エンティティにさらにフィルターを適用する方法ですWhere(w => w.Name == "abc")。少なくとも、settypeを作成してコンパイル可能なコードを取得することはできませんでしdynamicた。また、強力なタイピングをすべて失いたくありません。

于 2011-12-06T23:07:19.267 に答える