【问题标题】:How to get stored procedure to return results when called through Linq-to-SQL通过 Linq-to-SQL 调用时如何获取存储过程以返回结果
【发布时间】:2018-01-11 00:43:40
【问题描述】:

我有以下存储过程:

CREATE PROC [Scanner].[proc_AllContracts_Sel_Grid_Filter]
    (@SearchText VARCHAR(500), 
     @CampaignStartDate DATETIME = NULL, 
     @CampaignEndate DATETIME = NULL,
     @isPNPSelected BIT = NULL,
     @isSparSelected BIT = NULL,
     @isClicksSelected BIT = NULL)
AS  
    SET NOCOUNT ON;
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN
    SELECT       
        Sales.AccountManager.FirstName + N' ' + Sales.AccountManager.LastName AS AccountManagerName, 
        Sales.Contract.ContractNumber, 
        Sales.AccountManager.Code AS AccountManagerInitials_Code, 
        Client.Client.ClientName, 
        MAX(Sales.Burst.ChainName) AS ChainName,
        MAX(Sales.Burst.BrandName) AS BrandName, 
        MAX(Sales.Burst.MediaName) AS MediaType,  
        DATEDIFF(wk, Sales.vContractDates.FirstWeek, 
        Sales.vContractDates.LastInstallWeek) + 1 AS CampaignTotalRunningWeeks, 
        ISNULL(ISNULL(Sales.vContractDates.FirstWeek, Sales.Contract.SignDate), Sales.Contract.CreationDate) AS CampaignFirstWeek, 
        ISNULL(ISNULL(Sales.vContractDates.LastInstallWeek, Sales.Contract.SignDate), Sales.Contract.CreationDate) AS CampaignLastWeek, 
        DATEADD(wk, 1, ISNULL(ISNULL(Sales.vContractDates.LastInstallWeek, Sales.Contract.SignDate), 
        Sales.Contract.CreationDate)) AS ContractTerminationDate, 
        Sales.Contract.CreatedBy, 
        Sales.Contract.CreationDate, 
        Sales.Contract.Signed, 
        Sales.Contract.SignedBy, 
        Sales.Contract.SignDate, 
        Sales.Contract.ContractID,
        (SELECT COUNT(*) AS Expr1
         FROM Sales.StoreList WITH (NOLOCK) 
         INNER JOIN Sales.Burst AS b WITH (NOLOCK) ON Sales.StoreList.BurstID = b.BurstID
         WHERE (b.ContractID = Sales.Contract.ContractID) 
           AND (b.ChainName LIKE '%pick ''n pay%')) AS PNP_NumberOfStoresSelected,
       (SELECT COUNT(*) AS Expr1
        FROM Sales.StoreList AS StoreList_2 WITH (NOLOCK) 
        INNER JOIN Sales.Burst AS b WITH (NOLOCK) ON StoreList_2.BurstID = b.BurstID
        WHERE (b.ContractID = Sales.Contract.ContractID) 
          AND (b.ChainName LIKE '%Spar%')) AS Spar_NumberOfStoresSelected,
(SELECT        COUNT(*) AS Expr1
FROM            Sales.StoreList AS StoreList_1 INNER JOIN
                            Sales.Burst AS b ON StoreList_1.BurstID = b.BurstID
WHERE        (b.ContractID = Sales.Contract.ContractID) AND (b.ChainName LIKE '%Click%')) AS Clicks_NumberOfStoresSelected, 
     -- SELECTED FOR SCANNER DATA
      ISNULL(CAST(COALESCE([PriorYear_isSelectedForScannerData], [PriorPeriod_isSelectedForScannerData], [PostPeriod_isSelectedForScannerData])AS BIT), 0) AS isSelectedForScannerData,
      CAST(COALESCE([PriorYear_SelectedForScannerData_Date], [PriorPeriod_SelectedForScannerData_Date], [PostPeriod_SelectedForScannerData_Date])AS DATETIME) AS SelectedForScannerData_Date,
     -- PNP READY
      ISNULL(CAST(COALESCE([PriorYear_isPNPDataReadyForPRC], [PriorPeriod_isPNPDataReadyForPRC], [PostPeriod_isPNPDataReadyForPRC])AS BIT),0) AS PNP_isDataReadyForPRC, 
     -- SPAR READY
      ISNULL(CAST(COALESCE([PriorYear_isSPARDataReadyForPRC], [PriorPeriod_isSPARDataReadyForPRC], [PostPeriod_isSPARDataReadyForPRC])AS BIT),0) AS SPAR_isDataReadyForPRC,  
     -- CLICKS READY
      ISNULL(CAST(COALESCE([PriorYear_isCLICKSDataReadyForPRC], [PriorPeriod_isCLICKSDataReadyForPRC], [PostPeriod_isCLICKSDataReadyForPRC])AS BIT),0) AS CLICKS_isDataReadyForPRC,
      -- READY DATES 
      CAST(COALESCE([PriorYear_PNPReadyDate], [PriorPeriod_PNPReadyDate], [PostPeriod_PNPReadyDate])AS DATETIME) AS PNP_ReadyDate,
      CAST(COALESCE([PriorYear_CLICKSReadyDate], [PriorPeriod_CLICKSReadyDate], [PostPeriod_CLICKSReadyDate])AS DATETIME) AS CLICKS_ReadyDate,
      CAST(COALESCE([PriorYear_SPARReadyDate], [PriorPeriod_SPARReadyDate], [PostPeriod_SPARReadyDate])AS DATETIME) AS SPAR_ReadyDate,
     -- PNP SUBMISSION
      ISNULL(CAST(COALESCE([PriorYear_isPNPDataSubmittedForPRC], [PriorPeriod_isPNPDataSubmittedForPRC], [PostPeriod_isPNPDataSubmittedForPRC])AS BIT),0) AS PNP_isDataSubmittedForPRC, 
      CAST(COALESCE([PriorYear_PNPSubmissionDate], [PriorPeriod_PNPSubmissionDate], [PostPeriod_PNPSubmissionDate])AS DATETIME) AS PNP_SubmissionDate,
     -- CLICKS SUBMISSION
      ISNULL(CAST(COALESCE([PriorYear_isCLICKSDataSubmittedForPRC], [PriorPeriod_isCLICKSDataSubmittedForPRC], [PostPeriod_isCLICKSDataSubmittedForPRC])AS BIT),0) AS CLICKS_isDataSubmittedForPRC, 
      CAST(COALESCE([PriorYear_CLICKSSubmissionDate], [PriorPeriod_CLICKSSubmissionDate], [PostPeriod_CLICKSSubmissionDate])AS DATETIME) AS CLICKS_SubmissionDate,
     -- SPAR SUBMISSION
      ISNULL(CAST(COALESCE([PriorYear_isSPARDataSubmittedForPRC], [PriorPeriod_isSPARDataSubmittedForPRC], [PostPeriod_isSPARDataSubmittedForPRC])AS BIT),0) AS SPAR_isDataSubmittedForPRC, 
      CAST(COALESCE([PriorYear_SPARSubmissionDate], [PriorPeriod_SPARSubmissionDate], [PostPeriod_SPARSubmissionDate])AS DATETIME) AS SPAR_SubmissionDate,
      ISNULL(COUNT([NovaDB].[Scanner].BarcodeRequest.ID),0) AS barcodecount

FROM            Client.Client INNER JOIN
                        Sales.Contract WITH (NOLOCK) ON Client.Client.ClientID = Sales.Contract.ClientID INNER JOIN
                        Sales.AccountManager WITH (NOLOCK) ON Sales.Contract.AccountManagerID = Sales.AccountManager.AccountManagerID INNER JOIN
                        Sales.Burst WITH (NOLOCK) ON Sales.Contract.ContractID = Sales.Burst.ContractID INNER JOIN
                        Sales.vVisibleContractList WITH (NOLOCK) ON Sales.Contract.ContractID = Sales.vVisibleContractList.ContractID LEFT OUTER JOIN
                        [NovaDB].[Scanner].[DataRequest] WITH (NOLOCK) ON Sales.Contract.ContractNumber = [NovaDB].[Scanner].[DataRequest].[ContractNumber] LEFT OUTER JOIN
                        Sales.vContractDates WITH (NOLOCK) ON Sales.Contract.ContractID = Sales.vContractDates.ContractID LEFT OUTER JOIN [NovaDB].[Scanner].BarcodeRequest ON [NovaDB].[Scanner].[DataRequest].ID = [NovaDB].[Scanner].BarcodeRequest.DataRequestId
WHERE        (Sales.Contract.Cancelled = 0) AND (Sales.Contract.Signed = 1)

                          --DYNAMIC WHERE CLAUSE FOR VARIOUS PARAMETERS WHICH MAY OR MAY NOT BE PASSED IN::

                         AND (@CampaignStartDate IS NULL OR ISNULL(ISNULL(Sales.vContractDates.FirstWeek, Sales.Contract.SignDate), Sales.Contract.CreationDate) >= @CampaignStartDate)
                         AND (@CampaignEndate IS NULL OR ISNULL(ISNULL(Sales.vContractDates.LastInstallWeek, Sales.Contract.SignDate), Sales.Contract.CreationDate) <= @CampaignEndate)

                          -- ONLY ONE STORE CAN BE SELECTED AT A TIME

                         AND 

                         (@isPNPSelected IS NULL OR @isPNPSelected = 1 OR Sales.Burst.ChainName LIKE N'%pick ''n pay%')
                         OR  (@isSparSelected IS NULL OR @isSparSelected = 1 OR Sales.Burst.ChainName LIKE N'%Spar%')
                         OR  (@isClicksSelected IS NULL OR @isClicksSelected =1 OR Sales.Burst.ChainName LIKE N'%Clicks%')

                         AND 

                         -- FILTER BY 1.) Chain. 2)Media Type. 3) ClientName. 4) BrandName. 5) ContractNumber

                         (@SearchText IS NULL OR @SearchText = '' 
                         OR Sales.AccountManager.FirstName LIKE N'%' + @SearchText + '%'
                         OR Sales.AccountManager.LastName LIKE N'%' + @SearchText + '%'
                         OR Sales.Burst.ChainName LIKE N'%' + @SearchText + '%'
                         OR Sales.Burst.MediaName LIKE N'%' + @SearchText + '%'
                         OR Client.Client.ClientName LIKE N'%' + @SearchText + '%' 
                         OR Sales.Burst.BrandName LIKE N'%' + @SearchText + '%' 
                         OR Sales.Contract.ContractNumber LIKE N'%' + @SearchText + '%')

GROUP BY Sales.AccountManager.FirstName + N' ' + Sales.AccountManager.LastName, 
         Sales.Contract.ContractNumber, 
         Sales.AccountManager.Code, 
         Client.Client.ClientName, 
         DATEDIFF(wk, Sales.vContractDates.FirstWeek,Sales.vContractDates.LastInstallWeek) + 1, 
         ISNULL(ISNULL(Sales.vContractDates.FirstWeek, Sales.Contract.SignDate), Sales.Contract.CreationDate), 
         ISNULL(ISNULL(Sales.vContractDates.LastInstallWeek,Sales.Contract.SignDate), Sales.Contract.CreationDate), 
         DATEADD(wk, 1, ISNULL(ISNULL(Sales.vContractDates.LastInstallWeek, Sales.Contract.SignDate), Sales.Contract.CreationDate)), 
         Sales.Contract.CreatedBy, 
         Sales.Contract.CreationDate, 
         Sales.Contract.SignedBy, 
         Sales.Contract.SignDate, 
         Sales.Contract.Signed, 
         Sales.Contract.ContractID,
      -- SELECTED FOR SCANNER DATA
      CAST(COALESCE([PriorYear_isSelectedForScannerData], [PriorPeriod_isSelectedForScannerData], [PostPeriod_isSelectedForScannerData])AS BIT),
      CAST(COALESCE([PriorYear_SelectedForScannerData_Date], [PriorPeriod_SelectedForScannerData_Date], [PostPeriod_SelectedForScannerData_Date])AS DATETIME),
     -- PNP READY
      CAST(COALESCE([PriorYear_isPNPDataReadyForPRC], [PriorPeriod_isPNPDataReadyForPRC], [PostPeriod_isPNPDataReadyForPRC])AS BIT),  
      CAST(COALESCE([PriorYear_PNPReadyDate], [PriorPeriod_PNPReadyDate], [PostPeriod_PNPReadyDate])AS DATETIME),
      CAST(COALESCE([PriorYear_CLICKSReadyDate], [PriorPeriod_CLICKSReadyDate], [PostPeriod_CLICKSReadyDate])AS DATETIME),
      CAST(COALESCE([PriorYear_SPARReadyDate], [PriorPeriod_SPARReadyDate], [PostPeriod_SPARReadyDate])AS DATETIME),
     -- PNP SUBMISSION
      CAST(COALESCE([PriorYear_isPNPDataSubmittedForPRC], [PriorPeriod_isPNPDataSubmittedForPRC], [PostPeriod_isPNPDataSubmittedForPRC])AS BIT), 
      CAST(COALESCE([PriorYear_PNPSubmissionDate], [PriorPeriod_PNPSubmissionDate], [PostPeriod_PNPSubmissionDate])AS DATETIME),
       -- CLICKS READY
      CAST(COALESCE([PriorYear_isCLICKSDataReadyForPRC], [PriorPeriod_isCLICKSDataReadyForPRC], [PostPeriod_isCLICKSDataReadyForPRC])AS BIT),  
     -- CLICKS SUBMISSION
      CAST(COALESCE([PriorYear_isCLICKSDataSubmittedForPRC], [PriorPeriod_isCLICKSDataSubmittedForPRC], [PostPeriod_isCLICKSDataSubmittedForPRC])AS BIT), 
      CAST(COALESCE([PriorYear_CLICKSSubmissionDate], [PriorPeriod_CLICKSSubmissionDate], [PostPeriod_CLICKSSubmissionDate])AS DATETIME),
      -- SPAR READY
      CAST(COALESCE([PriorYear_isSPARDataReadyForPRC], [PriorPeriod_isSPARDataReadyForPRC], [PostPeriod_isSPARDataReadyForPRC])AS BIT),  
     -- SPAR SUBMISSION
      CAST(COALESCE([PriorYear_isSPARDataSubmittedForPRC], [PriorPeriod_isSPARDataSubmittedForPRC], [PostPeriod_isSPARDataSubmittedForPRC])AS BIT), 
      CAST(COALESCE([PriorYear_SPARSubmissionDate], [PriorPeriod_SPARSubmissionDate], [PostPeriod_SPARSubmissionDate])AS DATETIME)
      return
END

我创建了一个 LINQ To SQL dbml 并将存储过程拖到上面,这就是我的称呼:

using (var db = new Contexts.Connections().ScannerDataToolDB())
{
    var allContractsList = db.proc_AllContracts_Sel_Grid_Filter(SearchText, CampaignStartDate, CampaignEndate, isPNPSelected, isSparSelected, isClicksSelected).ToList();
}

存储过程存在三个问题:

  1. 我测试了@SearchText 参数(将 null 传递给所有其他参数),它基本上什么都不做。换句话说,它没有任何效果 - 无论我将其保留为 null 还是为其赋予与列中的数据相关的值,它都会返回相同的结果(所有列)。

    请帮我解决这个问题。我无法弄清楚问题是什么。我正在尝试编写“安全”的动态 SQL。

  2. 我遇到的第二个问题是 C# 代码没有中断,但它没有返回任何值。 0 个结果。我知道问题出在查询的编写方式上,因为我测试了我的 dbml 是否可以与其他存储过程一起使用(并且它们检索数据很好),包括更改此 proc 的主体以返回如下内容:

    Select * Sales.Contract.ContractNumber
    

    它返回了 +800 000 条记录。

我测试了其他参数,它们似乎没有任何效果。

EXEC    [Scanner].[proc_AllContracts_Sel_Grid_Filter]
        @SearchText = '',
        @CampaignStartDate =  @srtDate,
        @CampaignEndate = @endDate,
        @isPNPSelected = 1,
        @isSparSelected = 1,
        @isClicksSelected = 1

查询甚至生成了以下警告消息:

警告:空值被聚合或其他 SET 操作消除。

我做错了什么?请帮帮我。

【问题讨论】:

  • 只是一些建议: 1. 不要使用Linq to SQL,它几乎已经死了,没有进一步开发。使用您会发现非常相似的实体框架。 2. 首先制作一个简单得多的程序以使其正常工作。 3.在此之前验证您是否可以做一些更简单的事情,例如 var data = context.yourtable.ToList();返回数据。 4.您似乎有多个故障,从数据库开始工作并确定为什么您的 proc 没有获取数据。您提供的过程相当大且专有,您不能指望有人知道您的数据并修复他们不知道的过程。
  • 另一个建议。在继续使用 NOLOCK 乱扔查询之前,请阅读本文。 blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere 这比大多数人意识到的要险恶得多。
  • 谢谢你们的cmets。该查询确实返回了结果,它只是没有按照我想要的方式过滤。换句话说,我的 where 子句以及它如何处理参数是问题所在。请看一下逻辑。

标签: c# sql-server linq stored-procedures


【解决方案1】:

您可以将存储过程拖到设计器上并使用它,就像您在其他存储过程中看到的那样。尝试澄清您遇到的问题。

  1. 是否将参数传递到数据库? Attach the profiler to your SQL Server instance and trace the command。您将立即能够查看是否有任何内容传递给您的存储过程。

  2. 直接测试您的存储过程 - 从 SQL Management Studio。它有效吗?

  3. 假设您的 SQL 工作正常,log the command you are sending。 LINQ-to-SQL 可以轻松输出它发送的每个命令。如果命令符合预期,那么您的存储过程是可疑的。如果命令与预期不符,则您的 C# 存在问题。

  4. 调试 LINQ-to-SQL 代码。 dbml 文件生成许多可以调试的类。在那里放置一些断点并检查您传递的参数。

看起来您正在将 classes 传递给方法 (SearchText, CampaignStartDate, CampaignEndate),但我强烈怀疑您只是大小写不一致。除非您对正在传递的这些对象的属性做一些聪明的事情,否则这应该可以工作。

【讨论】:

  • 让我解释一下。我只是使用 LINQ to SQL 来调用我的存储过程。换句话说,我从不将表拖到 dbml 以从它们生成对象类。所以这些(SearchText、CampaignStartDate、CampaignEndate)只是从我的视图模型传递到我的方法中的参数值(属性),它会命中存储的过程。我在 SQL 中测试了我的过程并返回结果,它只是不过滤出色地。换句话说,我的逻辑在 where 子句中失败了。但是在另一端,当我的 c# 代码调用 proc 时,它不会返回任何内容。我将使用您的广告进行调试。
猜你喜欢
  • 1970-01-01
  • 2010-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 2011-03-07
相关资源
最近更新 更多