条件付きでインクルードし、次にインクルードする

c# entity-framework entity-framework-core linq-to-entities

質問

EF-Coreによく知られているように、遅延ロードはありません。そのような意味で、私はいくつかの後から考えて質問しなければなりません。だから私は考えなければならないので、それを正しくやろうとするかもしれない。

私はかなり標準的な更新クエリを持っていますが、私はいつもHeaderImagePromoImage FKオブジェクトを含める必要はないと思っていました。それを実現させる方法があるはずです。しかし、後でIncludeを実行する方法は見つけられません。事実、私は実際にオブジェクトを実際に作業する前に、おそらくこれを含めることを望みます。そうすれば、私は熱心を自動化することができます。

ArticleContent ac = _ctx.ArticleContents
    .Include(a=> a.Metadata)
    .Include(a=> a.HeaderImage)
    .Include(a=> a.PromoImage)
    .Single(a => a.Id == model.BaseID);

ac.Title = model.Title;
ac.Ingress = model.Ingress;
ac.Body = model.Body;
ac.Footer = model.Footer;

if (model.HeaderImage != null)
{
    ac.HeaderImage.FileURL = await StoreImage(model.HeaderImage, $"Header_{model.Title.Replace(" ", "_")}_{rand.Next()}");
}
if (model.PromoImage != null)
{
    ac.PromoImage.FileURL = await StoreImage(model.PromoImage, $"Promo_{model.Title.Replace(" ", "_")}_{rand.Next()}");
}

ac.Metadata.EditedById = uId;
ac.Metadata.LastChangedTimestamp = DateTime.Now;

await _ctx.SaveChangesAsync();

エクストラ

明確にするために、これはEF7(Core)であり、最初の_ctx.ArticleContents.Include(a=> a.Metadata).Single(a => a.Id == model.BaseID).

人気のある回答

私はAlexander Derckのソリューションに似た何かを使っています。 (コメントに記載されている例外について:ctx.ArticleContents.AsQueryable()も機能するはずです)。

私はBaseAdminControllerを使用しているいくつかのCRUD MVCサイトについては、導かれた具体的なコントローラでは、Includesを動的に追加できます。 BaseAdminControllerから:

// TModel: e.g. ArticleContent
private List<Expression<Func<TModel, object>>> includeIndexExpressionList = new List<Expression<Func<TModel, object>>>();

protected void AddIncludes(Expression<Func<TModel, object>> includeExpression)
{
    includeIndexExpressionList.Add(includeExpression);
}

後で私は柔軟性が必要であることを知ったので、私はクエリ可能なものを追加しました。例えばThenInclude()のように。

private Func<IQueryable<TModel>, IQueryable<TModel>>  IndexAdditionalQuery { get; set; }

protected void SetAdditionalQuery(Func<IQueryable<TModel>, IQueryable<TModel>> queryable)
{
    IndexAdditionalQuery = queryable;
}

ここでIndexアクション:

public virtual async Task<IActionResult> Index()
{
    // dynamic include:
    // dbset is for instance ctx.ArticleContents
    var queryable = includeIndexExpressionList
        .Aggregate(dbSet.AsQueryable(), (current, include) => current.Include(include));
    if(IndexAdditionalQuery != null) queryable = IndexAdditionalQuery(queryable);
    var list = await queryable.Take(100).AsNoTracking().ToListAsync();
    var viewModelList = list.Map<IList<TModel>, IList<TViewModel>>();

    return View(viewModelList);
}

私が使用する具体的なコントローラでは、

AddIncludes(e => e.EventCategory);

SetAdditionalQuery(q => q
    .Include(e => e.Event2Locations)
    .ThenInclude(j => j.Location));


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ