0

我是实体框架的新手。这是我第一个使用它的项目。

我创建了一个新类,它使用新属性扩展了我的“商家”实体,这些属性主要是计算的总数。我想不出用数据填充这些新属性的最佳方法。我正在使用微风.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;

    }
4

2 回答 2

0

谢谢大家的指导。最接近的建议是关于使用 oData 的建议。我研究了急切加载,但这似乎适用于连接实体,并且这些属性无法组合。我可能会用“include”做更多的研究,以确定它是否可以用来加载单个属性,但我找不到任何关于它的文档。另一件接近的事情是投影,但 EF 不允许投影到相同的类型。我本可以投影到部分课程,但随后我会失去微风需要的元数据。如果不是微风,那将是一个非常好的解决方案。最后,虽然 Breeze 确实支持 oData,但它有太多限制(例如无法缓存),所以我想继续使用 IQueryable。

这就是我想出的。它现在只循环当前页面,但它仍然对主查询进行计数,因此 Breeze 可以在客户端上进行分页。这一切都是可能的,因为 Breeze 允许我发送获取参数,以便我可以将分页卸载到服务器。这需要大量的研究,它仍然不是完美的,但它的加载速度非常快,所以我现在必须继续前进。

    [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()
        };

    }
于 2013-09-23T22:26:05.450 回答
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;
}

usings

using System.Web.Http;
using System.Web.Http.OData;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Query;
于 2013-09-23T10:19:53.930 回答