加速大型Linq到实体调用MVC3

时间:2012-06-03 23:55:24

标签: asp.net-mvc-3 entity-framework c#-4.0 linq-to-entities

下面是我正在使用的代码,它正在提取的数据库表中包含大约92000条记录。它正在拉动的方式是拉动所有92000条记录,然后进行过滤。 我要做的是对数据库的初始拉取进行过滤,这样就不需要花费大约40秒的时间来加载页面。 这是我仍然是新手,所以我迷失了如何做到这一点并让它与我的观点一起工作

public ViewResult Makes()
{
    var items = (from item in DBCacheHelper.recallslist
                 orderby item.MFGTXT ascending
                 select item.ToDomainRecall()).GroupBy(item => item.MFGTXT).Select(grp => grp.First());


    return View(items);
}

public static IEnumerable<Recall> recallslist
{
    get
    {
        if (c["GetAllRecalls"] == null)
        {
            c.Insert("GetAllRecalls", GetAllRecalls());
            return (IEnumerable<Recall>)c["GetAllRecalls"];
        }
        else
        {
            return (IEnumerable<Recall>)c["GetAllRecalls"];
        }
    }
}



public static IEnumerable<Recall> GetAllRecalls()
{
    using (DealerContext context = new DealerContext())
    {
        var items = from item in context.recalls.ToList<Recall>()
                     select item.ToDomainRecall();
        return items.ToList<Recall>();
    }
}


SELECT 
[Extent1].[RecallsId] AS [RecallsId], 
[Extent1].[RECORD_ID] AS [RECORD_ID], 
[Extent1].[CAMPNO] AS [CAMPNO], 
[Extent1].[MAKETXT] AS [MAKETXT], 
[Extent1].[MODELTXT] AS [MODELTXT], 
[Extent1].[YEARTXT] AS [YEARTXT], 
[Extent1].[MFGCAMPNO] AS [MFGCAMPNO], 
[Extent1].[COMPNAME] AS [COMPNAME], 
[Extent1].[MFGNAME] AS [MFGNAME], 
[Extent1].[BGMAN] AS [BGMAN], 
[Extent1].[ENDMAN] AS [ENDMAN], 
[Extent1].[RCLTYPECD] AS [RCLTYPECD], 
[Extent1].[POTAFF] AS [POTAFF], 
[Extent1].[ODATE] AS [ODATE], 
[Extent1].[INFLUENCED_BY] AS [INFLUENCED_BY], 
[Extent1].[MFGTXT] AS [MFGTXT], 
[Extent1].[RCDATE] AS [RCDATE], 
[Extent1].[DATEA] AS [DATEA], 
[Extent1].[RPNO] AS [RPNO], 
[Extent1].[FMVSS] AS [FMVSS], 
[Extent1].[DESC_DEFECT] AS [DESC_DEFECT], 
[Extent1].[CONEQUENCE_DEFECT] AS [CONEQUENCE_DEFECT], 
[Extent1].[CORRECTIVE_ACTION] AS [CORRECTIVE_ACTION], 
[Extent1].[NOTES] AS [NOTES], 
[Extent1].[RCL_CMPT_ID] AS [RCL_CMPT_ID]
FROM [dbo].[Recalls] AS [Extent1]

更新

最终我只想从召回表中提取MFGTXT等于的记录 AutoMake表中的MakeName

public class AutoMake
{
    [Key]
    public int MakeID { get; set; }
    public string MakeName { get; set; }

public AutoMake ToDomainAutoMakes()
{
    return new AutoMake
    {
        MakeID = this.MakeID,
        MakeName = this.MakeName
    };
}

}

public class Recall
{
    [Key]
    public int RecallsId { get; set; }
    public string RECORD_ID { get; set; }
    public string CAMPNO { get; set; }
    public string MAKETXT { get; set; }
    public string MODELTXT { get; set; }
    public string YEARTXT { get; set; }
    public string MFGCAMPNO { get; set; }
    public string COMPNAME { get; set; }
    public string MFGNAME { get; set; }
    public string BGMAN { get; set; }
    public string ENDMAN { get; set; }
    public string RCLTYPECD { get; set; }
    public string POTAFF { get; set; }
    public string ODATE { get; set; }
    public string INFLUENCED_BY { get; set; }
    public string MFGTXT { get; set; }
    public string RCDATE { get; set; }
    public string DATEA { get; set; }
    public string RPNO { get; set; }
    public string FMVSS { get; set; }
    public string DESC_DEFECT { get; set; }
    public string CONEQUENCE_DEFECT { get; set; }
    public string CORRECTIVE_ACTION { get; set; }
    public string NOTES { get; set; }
    public string RCL_CMPT_ID { get; set; }

    public Recall ToDomainRecall()
    {
        return new Recall
        {
            RECORD_ID = this.RECORD_ID,
            CAMPNO = this.CAMPNO,
            MAKETXT = this.MAKETXT,
            MODELTXT = this.MODELTXT,
            YEARTXT = this.YEARTXT,
            MFGCAMPNO = this.MFGCAMPNO,
            COMPNAME = this.COMPNAME,
            MFGNAME = this.MFGNAME,
            BGMAN = this.BGMAN,
            ENDMAN = this.ENDMAN,
            RCLTYPECD = this.RCLTYPECD,
            POTAFF = this.POTAFF,
            ODATE = this.ODATE,
            INFLUENCED_BY = this.INFLUENCED_BY,
            MFGTXT = this.MFGTXT,
            RCDATE = this.RCDATE,
            DATEA = this.DATEA,
            RPNO = this.RPNO,
            FMVSS = this.FMVSS,
            DESC_DEFECT = this.DESC_DEFECT,
            CONEQUENCE_DEFECT = this.CONEQUENCE_DEFECT,
            CORRECTIVE_ACTION = this.CORRECTIVE_ACTION,
            NOTES = this.NOTES,
            RCL_CMPT_ID = this.RCL_CMPT_ID

        };
    }
}

2 个答案:

答案 0 :(得分:0)

看起来你的DBaccess是在DBCacheHelper.recallslist的调用中完成的。

您需要编辑从/在此函数中运行的sql。

正如Eranga指出的那样,您没有显示如何将大数字过滤到较少数量的记录。我假设你一次想要20或100?如果是,请在此处查看接受的答案:

efficient way to implement paging

具体来说,这部分显示了如何只检索行x到y(其中x = @ p0 + 1和y = @ p0 + @ p1):

SELECT [t1].[CodCity], 
    [t1].[CodCountry], 
    [t1].[CodRegion], 
    [t1].[Name],  
    [t1].[Code]
FROM (
    SELECT ROW_NUMBER() OVER (
        ORDER BY [t0].[CodCity], 
        [t0].[CodCountry], 
        [t0].[CodRegion], 
        [t0].[Name],
        [t0].[Code]) AS [ROW_NUMBER], 
        [t0].[CodCity], 
        [t0].[CodCountry], 
        [t0].[CodRegion], 
        [t0].[Name],
        [t0].[Code]
    FROM [dbo].[MtCity] AS [t0]
    ) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
ORDER BY [t1].[ROW_NUMBER]

答案 1 :(得分:0)

如果要在存储库方法之外添加服务器端过滤,则需要将类型返回为IQueryable而不是IEnumerable,而不是调用.ToList,.AsEnumerable或任何其他可能导致调用.GetEnumerator的方法。另外,你的演员`(IEnumerable)c [“GetAllRecalls”];'强制LINQ to Objects用于后续请求,而不是保留表达式树并使用Entity Framework。话虽这么说,您可能需要将调用ToDomainRecall方法移动到应用其他过滤器后,因为无法将其转换为您的数据库。以下是您需要做出的一些更改:

public ViewResult Makes()
{
    var items = (from item in DBCacheHelper.recallslist
                 orderby item.MFGTXT ascending
                 select item.ToDomainRecall()).GroupBy(item => item.MFGTXT).Select(grp => grp.First());


    return View(items);
}

public static IQueryable<Recall> recallslist
{
    get
    {  
        if (c["GetAllRecalls"] == null)
        {
            c.Insert("GetAllRecalls", GetAllRecalls(context));
        }
        return c["GetAllRecalls"];

    }
}



public static IQueryable<Recall> GetAllRecalls(DealerContext context)
{
        var items = context.recalls;
        return items;
}