存储库模式和IQueryable<>生成错误的SQL

时间:2012-10-12 23:29:22

标签: sql asp.net-mvc-4 repository-pattern .net-4.5 entity-framework-5

我在小型.NET 4.5,MVC4,EF5项目上使用Repository Pattern。

我注意到如果我改变从存储库传递的IQueryable对象的结果,生成的SQL就不太理想了。

例如,在我的存储库中:

    public IQueryable<Entry> GetEntries()
    {
        // (db is an instance of the data context)
        return db.Entries.Where(e => e.UserId == WebSecurity.CurrentUserId);
    }

在我的控制器中,我限制返回的行数并对其进行排序:

    public ActionResult Index()
    {
        // (repo is an instance of the repository object)
        var entries = repo.GetEntries().Take(10).OrderByDescending(o => o.Created)
        return View(entries);
    }

这将生成以下SQL:

DECLARE @p__linq__0 int = 1

SELECT 
[Project1].[UserId] AS [UserId], 
[Project1].[Id] AS [Id], 
[Project1].[Created] AS [Created], 
[Project1].[LastModified] AS [LastModified], 
[Project1].[BodyOriginal] AS [BodyOriginal], 
[Project1].[BodyFormatted] AS [BodyFormatted], 
[Project1].[FormatterVersion] AS [FormatterVersion], 
[Project1].[BodyDigest] AS [BodyDigest], 
[Project1].[FollowupId] AS [FollowupId], 
[Project1].[AddMethod] AS [AddMethod], 
[Project1].[Entry_Id] AS [Entry_Id]
FROM ( SELECT 
        [Extent1].[Id] AS [Id], 
        [Extent1].[UserId] AS [UserId], 
        [Extent1].[Created] AS [Created], 
        [Extent1].[LastModified] AS [LastModified], 
        [Extent1].[BodyOriginal] AS [BodyOriginal], 
        [Extent1].[BodyFormatted] AS [BodyFormatted], 
        [Extent1].[FormatterVersion] AS [FormatterVersion], 
        [Extent1].[BodyDigest] AS [BodyDigest], 
        [Extent1].[FollowupId] AS [FollowupId], 
        [Extent1].[AddMethod] AS [AddMethod], 
        [Extent1].[Entry_Id] AS [Entry_Id]
        FROM [dbo].[Entries] AS [Extent1]
        WHERE [Extent1].[UserId] = @p__linq__0
)  AS [Project1]
ORDER BY [Project1].[Created] DESC  

如您所见,生成的SQL非常冗余。

如果我更改存储库方法以包含截断和排序结果:

    public IQueryable<Entry> GetEntries()
    {
        // (db is an instance of the data context)
        return db.Entries.Where(e => e.UserId == WebSecurity.CurrentUserId).Take(10).OrderByDescending(o => o.Created);
    }

生成的SQL更好:

DECLARE @p__linq__0 int = 1

SELECT 
            [Extent1].[Id] AS [Id], 
            [Extent1].[UserId] AS [UserId], 
            [Extent1].[Created] AS [Created], 
            [Extent1].[LastModified] AS [LastModified], 
            [Extent1].[BodyOriginal] AS [BodyOriginal], 
            [Extent1].[BodyFormatted] AS [BodyFormatted], 
            [Extent1].[FormatterVersion] AS [FormatterVersion], 
            [Extent1].[BodyDigest] AS [BodyDigest], 
            [Extent1].[FollowupId] AS [FollowupId], 
            [Extent1].[AddMethod] AS [AddMethod], 
            [Extent1].[Entry_Id] AS [Entry_Id]
            FROM [dbo].[Entries] AS [Extent1]
            WHERE [Extent1].[UserId] = @p__linq__0
  ORDER BY [Extent1].[Created] DESC  

我如何克服这个问题,即利用存储库模式,同时仍然可以灵活地修改存储库的结果,而不会创建构造不良的SQL?

1 个答案:

答案 0 :(得分:1)

这是存储库反模式,最好删除该“存储库”。如果您确实想使用Repository,请定义一个与EF无关的接口,并且没有方法返回IQueryable。此外,存储库的使用与否与EF生成sql的方式无关。