我正在创建一个WebAPI供移动应用程序以及我们的ASP.NET MVC4 webapp使用。我们正在使用庞大的数据库,因此我们需要尽可能避免实现实体列表。我们的WebAPI返回JSON。
情况很简单......收到了许可证列表的请求,但必须对其进行分页,因为有500,000条记录可以返回。在将它们转换为返回的viewmodel列表之前,如何将分页/过滤应用于IQueryable实体列表?
以下是我正在使用的一些测试代码......
// Get the list of licenses, but page them.
// GET api/<controller>
//[Queryable]
public IQueryable<LicenseViewModel> Get()
{
Mapper.CreateMap<LicenseEntity, LicenseViewModel>();
Mapper.AssertConfigurationIsValid();
List<LicenseViewModel> vms = new List<LicenseViewModel>();
using (var repo = new LicenseRepository())
{
// Get the IQueryable<LicenseEntity> list...
// IS THERE SOME WAY TO APPY PAGING/FILTERING HERE?
var entities = repo.List();
// Convert them to viewmodels. ARGGG! This will materialize the huge list
// if we cannot applyfiltering/paging in the previous step.
foreach (var item in entities)
{
var vm = Mapper.Map<LicenseEntity, LicenseViewModel>(item);
list.Add(vm);
}
}
return vms.AsQueryable();
}
我尝试了以下操作,但在尝试展开列表并查看结果时收到“儿童无法回避”错误。
using (var repo = new LicenseRepository())
{
// Get the list of entities...
var list = repo
.List()
.Select(x => Mapper.Map(x, new LicenseViewModel()));
return list;
}
感谢您的时间和建议,
麦克
答案 0 :(得分:0)
不确定这是如何映射到Web API的,但主体是相同的。
WCF Dataservices基本相同,但我相信目前有一些额外功能,您可以设置页面大小如下:
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetPageSize("*", 20);
}
&#34; *&#34;插入您的实体集名称。
通过设置此项,Feed将包含一个延续令牌,客户端可以使用该令牌来请求下一页。
在您的存储库中,您可能需要根据数据源手动处理Take和Skip功能。
如果网址包含?$ top = 10&amp; $ skip = 0,那么您可以将其添加到您的数据源请求中,请参阅下面的示例。
using (var repo = new LicenseRepository())
{
// Get the list of entities...
var list = repo
.Select(x => Mapper.Map(x, new LicenseViewModel()))
.Skip(0)
.Take(10);
return list;
}
显然,根据网址的$ top和$ skip元素中的内容更改skip / take值。
答案 1 :(得分:0)
对于分页,您可以使用我们最近添加的ResultLimit功能。你可以说,
[Queryable(ResultLimit=10)]
一次只能返回10个项目。
而且,最酷的部分是我们计算下一页链接。下一页链接是客户端为了获取下一页而应该遵循的链接。如果您使用的是ODataFormatter,则默认情况下,响应中会包含下一页链接。如果您使用不同的格式化程序,我们只计算链接但不要将其放入响应正文中,因为我们不知道它的格式。你可以编写一个消息处理程序或一个动作过滤器来从
中检索链接Request.Properties['MS_NextPageLink']
并将其写入响应正文或响应标题或客户期望的任何位置。
答案 2 :(得分:0)
//获取LicenseEntity对象的IQueryable列表。 var entityList = LicenseRepository.List(adapter);
//将列表转换为IQueryable列表 // LicenseViewModel对象。 var vmList = entityList.Select(x =&gt; AutoMapper.Mapper.Map(x,new LicenseViewModel()));
答案 3 :(得分:0)
我找到了将域实体投影到视图模型的解决方案。如果您遇到与我相同的问题,请查看以下链接:
http://lostechies.com/jimmybogard/2011/02/09/autoprojecting-linq-queries/ http://www.devtrends.co.uk/blog/stop-using-automapper-in-your-data-access-code
顺便说一句,在一个我的域实体中,我有一个带有一些“计算”属性的部分类...其值是从数据库记录中的其他字段生成的属性。这些不能在域实体中,因为它们会干扰上述解决方案。我把它们移到我的ViewModel类,这是他们真正需要的地方,一切都很好。
希望这些信息有助于......
麦克