正如EF-Core中众所周知的那样,没有延迟加载。所以这种意味着我不得不在事后做一些事情。所以,既然我必须思考,那么我也可以尝试正确地做到这一点。
我有一个相当标准的更新查询,但我认为嘿,我并不总是要包含HeaderImage
和PromoImage
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();
EXTRA
要明确的是,这是 EF7(核心),并且我在允许我按需添加的解决方案之后,希望在初始_ctx.ArticleContents.Include(a=> a.Metadata).Single(a => a.Id == model.BaseID).
之后
答案 0 :(得分:1)
我正在使用类似Alexander Derck的解决方案。 (关于评论中提到的例外:ctx.ArticleContents.AsQueryable()也应该有用。)
对于几个CRUD MVC网站,我使用的是BaseAdminController
。在派生的具体控制器中,我可以动态添加包含。从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);
}
后来我发现我需要更多的灵活性,所以我添加了一个可查询的。例如。 for ThenInclude()。
private Func<IQueryable<TModel>, IQueryable<TModel>> IndexAdditionalQuery { get; set; }
protected void SetAdditionalQuery(Func<IQueryable<TModel>, IQueryable<TModel>> queryable)
{
IndexAdditionalQuery = queryable;
}
这里的索引动作:
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));
答案 1 :(得分:0)
我会创建一个获取数据的方法,该方法将属性包含在表达式中:
static ArticleContent GetArticleContent(int ID,
params Expression<Func<ArticleContent, object>>[] includes)
{
using(var ctx = new MyContext())
{
var acQuery = _ctx.ArticleContents.Include(a=> a.Metadata);
foreach(var include in includes)
acQuery = acQuery.Include(include);
return acQuery.Single(a => a.Id == model.BaseID);
}
}
然后在主要方法中:
var ac = GetArticleContent(3, a => a.HeaderImage, a => a.PromoImage);