我是Entity Framework的新手。这是我的第一个使用它的项目。
我创建了一个新类,用新属性扩展我的“商家”实体,这些属性主要是计算总数。我无法找出用数据填充这些新属性的最佳方法。我正在使用breeze.js来查询iQueryable端点,所以我需要保持这个功能不变。
我找到了以下解决方案,但它非常慢,因为我必须遍历每条记录。尽管我已经在微风中实现了分页,但循环仍然会击中每一条记录,尽管它只返回一页。我猜这就是实体框架的工作原理。我的问题是如何在不循环的情况下填充扩展属性?
这是我的代码可行,但速度很慢。我可以消除此循环并使用值填充该扩展属性吗?
[HttpGet]
public IQueryable<Merchant> MerchantList()
{
IQueryable<Merchant> items = _repo.Context.Merchants;
foreach (var item in items)
{
// Total Stores
item.TotalStores = myMethod(item.MerchantUID);
}
return items;
}
答案 0 :(得分:0)
从它的外观来看,你正在循环遍历整个表格的数据,因为有人会得到某些行。我对Breeze
并不熟悉,但之前我曾与OData
合作过,所以希望这个解决方案对您有用。
我建议您停止公开IQueryable<>
并在内部管理查询。这样,您就可以将附加信息仅添加到要返回给客户端的记录中。这里有一些粗略的代码可以指出正确的方向:
[HttpGet]
public PageResult<Merchant> MerchantList(
ODataQueryOptions<Merchant> queryOptions)
{
var t = new ODataValidationSettings() { MaxTop = 25 };
var s = new ODataQuerySettings() { PageSize = 25 };
queryOptions.Validate(t);
IEnumerable<Merchant> results =
(IEnumerable<Merchant>)queryOptions.ApplyTo(_repo.Context.Merchants, s);
int skip = queryOptions.Skip == null ? 0 : queryOptions.Skip.Value;
int take = queryOptions.Top == null ? 25 : queryOptions.Top.Value;
long? count = Request.GetInlineCount();
List<Merchant> pageOfResults = results.Skip(skip).Take(take).ToList();
PageResult<Merchant> page =
new PageResult<Merchant>(
pageOfResults,
Request.GetNextPageLink(),
Request.GetInlineCount());
foreach (var item in page)
{
// Total Stores
item.TotalStores = myMethod(item.MerchantUID);
}
return page;
}
和using
s
using System.Web.Http;
using System.Web.Http.OData;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Query;
答案 1 :(得分:0)
感谢大家的指导。最接近的建议是关于使用oData的建议。我研究了急切加载,但这似乎适用于加入实体,这些属性无法组合。我可能会用“include”做更多的研究,以确定它是否可以用于加载单个属性,但我找不到任何使用它的文档。接近的另一件事是投影,但EF不允许投射到相同的类型。我可以预测到一个部分类,但后来我会松开微风所需的MetaData。如果不是微风,那将是一个非常好的解决方案。最后,虽然Breeze确实支持oData,但它有太多的限制(例如无法缓存),所以我想继续使用IQueryable。
这就是我想出的。它现在只循环遍历当前页面,但它仍然计算主查询,因此Breeze可以在客户端上进行分页。这是可能的,因为Breeze允许我发送get参数,以便我可以将分页卸载到服务器。这需要大量的研究,但仍然不是很完美,但它确实非常快,所以我现在必须继续前进。
[HttpGet]
[BreezeQueryable]
public QueryResult MerchantList(int take, int skip)
{
IQueryable<Merchant> main = _repo.Context.Merchants.OrderBy(m => m.MerchantUID);
IQueryable<Merchant> items = main.Skip(skip).Take(take);
foreach (var item in items)
{
// Total LifetimeVal
item.LifetimeVal= TotalLifetimeVal(item.MerchantUID);
// Total Stores
item.TotalStores = TotalStores(item.MerchantUID);
}
// return items;
return new QueryResult
{
InlineCount = main.Count(),
Results = items.ToList()
};
}