[英]How can I populate Extended Methods with EF5 and return IQueryable (without looping)
我是实体框架的新手。 这是我第一个使用它的项目。
我创建了一个新类,将新的属性扩展为“商人”实体,这些属性大多是计算得出的总数。 我想不出用数据填充这些新属性的最佳方法。 我正在使用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;
}
从外观上看,您正在遍历整个表中有价值的数据,这是某人偶然获得某些行的机会。 我对Breeze
并不熟悉,但是我曾经与OData
合作过,所以希望该解决方案对您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;
谢谢大家的指导。 最接近的建议是关于使用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()
};
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.