【问题标题】:LINQ generating SQL not supported by SQL Server 2008R2SQL Server 2008R2 不支持 LINQ 生成 SQL
【发布时间】:2015-06-16 09:52:26
【问题描述】:

我在 ASP.NET MVC 5 项目中使用 EF 6.1.3。虽然我的开发环境是 SQL Server 2012,但 QA 和 Production 都是在 SQL Server 2008 R2 上。

我有一份报告显示医生使用的前 5 个程序代码,所以我有一个简单的实体,包含 id、name、code1、code2、...code5。

构建 LINQ 查询有相当多的逻辑,基本上我得到一个医生列表和一个代码列表并加入它们。这是连接它们并选择前 5 个代码的代码:

var report =
    from pr in providerRiskLevels
    join nc in newCodes on pr.Provider.ProviderId equals nc.ProviderId
    where pr.RiskCategoryId == RIskScoreIds.VisibleRisk
        && (filterRiskLevelNums.Contains(pr.RiskLevelNum))
        && (filterSpecialtyId == 0 || pr.Provider.Specialty.SpecialtyId == filterSpecialtyId)
    select new ReportNewCodesEntity
    {
        ProviderId = pr.Provider.ProviderId,
        ProviderName = pr.Provider.Name,
        ProviderCode = pr.Provider.ProviderCode,
        SpecialtyName = pr.Provider.Specialty.Name,
        SpecialtyCode = pr.Provider.Specialty.SpecialtyCode,
        RiskScore = pr.RiskScore,
        RiskLevelName = pr.RiskLevelName,
        RiskLevelNum = pr.RiskLevelNum,
        NewCode1 = nc.Codes.OrderByDescending(c => c.Volume).FirstOrDefault().ProcedureCode,
        NewCode2 = nc.Codes.OrderByDescending(c => c.Volume).Skip(1).FirstOrDefault().ProcedureCode,
        NewCode3 = nc.Codes.OrderByDescending(c => c.Volume).Skip(2).FirstOrDefault().ProcedureCode,
        NewCode4 = nc.Codes.OrderByDescending(c => c.Volume).Skip(3).FirstOrDefault().ProcedureCode,
        NewCode5 = nc.Codes.OrderByDescending(c => c.Volume).Skip(4).FirstOrDefault().ProcedureCode
    };
return report;

问题是这四个Skip().FirstOrDefault() 生成的SQL 语法在SQL Server 2008 R2 上不可用:

 OFFSET x ROWS FETCH NEXT 1 ROWS ONLY 

其中 x = 1 到 4

我确信我可以将其移至存储过程(T-SQL 比 LINQ 好得多),但由于我一直在尝试掌握 LINQ,所以我想知道是否有:

  1. 一个指令告诉 LINQ 目标数据库的版本,以便生成兼容的代码
  2. 另一种提取前 5 个代码的方法。

我已经在 newCodes 中正确排序了代码(见下文),但没有 SKIP(需要它自己的排序子句)就无法选择它们。

var newCodes =
    from cc in codeCounts
    group cc by
        new {cc.ProviderId}
        into g
    select new ProviderNewCodesEntity
    {
        ProviderId = g.Key.ProviderId,
        Codes = g.OrderByDescending (x => x.Volume).Take(5).ToList()
    };

最好, 斯科特

【问题讨论】:

  • 问题当然是你的开发环境有一个更新版本的sql server,它支持offset...fetch子句。尝试在你的开发环境中使用 sql server 2008 r2,看看你会得到什么生成的 sql。 (我怀疑前 1 名不在前 4 名,或者类似的东西)
  • @Zohar,谢谢,当然是这样。我们知道风险(这就是为什么我们将 QA 保留在与 Prod 相同的版本上)。获得 2008 实例的工作量相当大,所以我尝试了另一种方法,我添加了它作为其他人的答案

标签: linq sql-server-2008-r2 entity-framework-6.1


【解决方案1】:

为了让 LINQ 生成兼容的代码,我们只是简单地编辑了生成的 EDMX 文件(不要尖叫,继续阅读)。

我们发现(在第 7 行)

<Schema Namespace="ComplianceRiskModel.Store" ProviderManifestToken="2012" Provider="System.Data.SqlClient"  ...>

改成

<Schema Namespace="ComplianceRiskModel.Store" ProviderManifestToken="2008" Provider="System.Data.SqlClient" ...>

为防止每次从数据库刷新模型时丢失此设置,我们正在添加一个构建任务以自动更新 BeforeBuild 目标中的 EDMX 文件,如 http://www.programmingmotility.com/2011/05/setting-providermanifesttoken-for-sql.html 中所述

最好, 斯科特

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-14
    • 2018-06-25
    • 1970-01-01
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多