繁体   English   中英

如何使用EF5填充扩展方法并返回IQueryable(无循环)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM