9

私のモデルでは、activeそれらすべてに属性があり、モデルが管理画面に表示されなかった場合、すべての非アクティブをフィルタリングしたいです。それを行う最良の方法は何ですか。現在使用しているのは次のとおりです

私の基本モデルクラスには、コレクションをフィルタリングするこのメソッドがあります

public virtual IQueryable<T> GlobalDefaultScope<T>(IQueryable<T> c) where T : CModel<T>
{
    if (settings.is_admin)
    {
        c = c.Where(m => m.active);
    }
    return c;
}

そして、すべての関係のモデルで、次の方法を実行しました

DbSet<T> set ...
var X = set.Where(some filter);
var list = globalDefaultScope(X).ToList();
return list;

そして今、コレクションをフィルタリングするそのコレクションのメソッドでinclude("Xmodel.Ymodel")呼び出されたを使用していくつかのサブリレーションを熱心にロードしたいときに、いくつかの深刻な問題が発生していますが、コレクション内のいくつかのアイテムが非アクティブな場合、この例外をスローし続けますglobalDefaultScopeget

System.InvalidOperationException: 操作に失敗しました: 1 つ以上の外部キー プロパティが null 非許容であるため、リレーションシップを変更できませんでした。

どうすればこれを修正できますか、またはこのフィルターをより洗練された方法で作成するにはどうすればよいですか。なぜなら、実装方法にあまり満足していないからです。

不足している情報、コード ブロック、または詳細についてお尋ねください

アップデート:

このリンクも見つけましたが、この方法では熱心に読み込まれたエントリでは機能しませんでした ( include())

更新 2:

これは、インクルードの使用方法とエラーが発生する場所の例です

私のモデルで

public IQueryable<Dish> getSomeRelation(bool eagerly_load_sub_relation1, bool eagerly_load_sub_relation2)
        {
            var query = getQuery(...);
            //getQuery =>  query = db.Entry(obj).Collection(collection).Query() 
            //GlobalDefaultScope(query)
            if ( eagerly_load_sub_relation1){
                query = query.Include(m => m.sub_relation1);
            }
            if (eagerly_load_sub_relation2){
                query = query.Include("sub_relation2.sub_relation_of_sub_relation2");
            }
            return query;
        }

インクルード内の関係をフィルタリングできませんでしたが、次のことを行いました。

private ICollection<SubRelation1> _sub_relation1 {get; set;}
public ICollection<SubRelation1> sub_relation1 {
get 
{
   //something like:
   return GlobalDefaultScope(_sub_relation1 ).ToList(); 
}  
set;}

sub_relation1 で結果をフィルタリングしているときに、db.SaveChanges() を実行すると、前述のエラーがスローされます。

4

2 に答える 2

8

次のような拡張メソッドを作成できます

public static IQueryable<T> Where<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate)
{
    source = source.Where("isActive == true"); // From System.linq.Dynamic Library
    source = Queryable.Where<T>(source, predicate);
    return source;
}

そしてそれらを次のように使用します

var user = db.UserProfiles.Include("webpages_Roles").Where(u => u.UserId < 30);

これでうまくいくはずです。さらに情報が必要な場合はお知らせください。

注:System.Linq.DynamicのNugetパッケージを追加して、動的Linqライブラリを作成してください

更新 1:

簡単なメンバーシップの webpages_Roles と UsreProfile テーブルに IsActive を含め、webpages_Roles を参照するもう 1 つのテーブル Role Priority も含めました。使いやすいように、すべての関係シップを 1 対多 (多から多) に変更しました。あなたのようなコードを使用すると、ロールのないユーザーがいると拡張メソッドでエラーが発生します。

すべてのユーザーに役割を与え、すべての役割を優先すると、エラーは発生しません。

他の情報が必要な場合はお知らせください。

更新 2

次のような1つの拡張メソッドを作成できます

public static IQueryable<T> WhereActive<T>(this IQueryable<T> source)
        {
            return source.Where("isActive == true"); // From System.linq.Dynamic Library
        }

のような他のメソッドを呼び出します

var user = db.UserProfiles.Include("webpages_Roles").WhereActive().Where(u => u.UserId < 30);

また

var user = db.UserProfiles.Include("webpages_Roles").WhereActive().FirstOrDefault(u => u.UserId < 30);

他の情報が必要な場合はお知らせください。

于 2013-09-12T13:58:40.263 に答える
2

次のように実行できます。

  1. OnModelCreating で、ソフト削除できるすべてのエンティティに IsDeleted 識別子を追加します
  2. SaveChanges をオーバーライドし、削除するすべてのエントリを見つける
  3. これらのエントリに対して SQL を実行して IsDeleted 識別子を設定し、状態を「分離」に設定します。
  4. 一意のインデックスを変更して、論理的に削除されたレコードを無視する

この回答で作業コードを見つけることができます: How to soft delete using Entity Framework Code First

于 2013-10-17T22:12:03.093 に答える