Linq to sql 如何在LINQtoSQL存储过程中使用临时表

Linq to sql 如何在LINQtoSQL存储过程中使用临时表,linq-to-sql,stored-procedures,vb.net-2010,Linq To Sql,Stored Procedures,Vb.net 2010,我在具有LINQ到SQL的存储过程中使用临时表。我将存储过程添加到Linq to SQL dbml文件中,然后出现项目错误消息 未知返回类型-无法检测到以下存储过程的返回类型。“ 当我在存储过程中删除一个临时表时,返回值就可以了 如何在具有Linq to SQL的存储过程中使用临时表 我用这样的方式来代替诱惑 CREATE TABLE tempTable( PartsReceivingID INT, SoPartID INT, RecvQty INT, ReturnQty INT ) 替

我在具有LINQ到SQL的存储过程中使用临时表。我将存储过程添加到Linq to SQL dbml文件中,然后出现项目错误消息

未知返回类型-无法检测到以下存储过程的返回类型。“

当我在存储过程中删除一个临时表时,返回值就可以了

如何在具有Linq to SQL的存储过程中使用临时表

我用这样的方式来代替诱惑

  CREATE TABLE tempTable(
PartsReceivingID INT, 
SoPartID INT,
RecvQty INT,
ReturnQty INT
)
替换如下所示

  SELECT @RowCount = count(*)           
  FROM Parts.studentTempTable          
   IF @RowCount > 0         
           BEGIN             
             TRUNCATE TABLE Parts.studentTempTable;
           END  
工作版本存储过程

ALTER  PROCEDURE [dbo].[stp_student_Select_New] 
                @pSchID as int, 
                @pCompanyID as int,
                @pAgingDate as int,
                @pTicketNo as VARCHAR(50),
                @pInvoiceNo as VARCHAR(50),
                @pDeliveryNo as VARCHAR(50),
                @pPartNo as VARCHAR(50)
As
SET NOCOUNT ON
BEGIN
          SELECT @RowCount = count(*)
          FROM Parts.studentTempTable

        IF @RowCount > 0
        BEGIN
            TRUNCATE TABLE Parts.studentTempTable;
        END


    ===============================================
    do something with studentTempTable
    ===============================================

        SELECT 
               r.Ticketid AS TicketID,
               r.SoPartNo  AS PartNo ,
               p.Description,
               r.InvoiceNo as InvoiceNo,
               r.InvoiceDate AS InvoiceDate,
               DATEDIFF(DY,r.InvoiceDate,GETDATE())as Aging,
               r.Qty AS CurrentInventory,              
               t.ReturnQty AS ReturnQty
        FROM Parts.studentTempTable AS t,
             Parts.PartsReceiving AS r,
             Parts.PartsInfo as p
        WHERE t.PartsReceivingID = r.PartsReceivingID
          --and i.TicketID = r.TicketID 
          and p.PartID = r.SoPartID  
          and t.ReturnQty >0 
          and DATEDIFF(DY,r.InvoiceDate,GETDATE()) > @pAgingDate
          and r.SchID = @pSchID 
          and r.CompanyID = @pCompanyID
          and r.SoPartNo like  '%%' + @pTicketNo + '%' 
          and r.InvoiceNo like  '%%' + @pInvoiceNo + '%' 
          and r.SoPartNo like  '%%' + @pPartNo + '%' 
          --and i.TicketNo like  '%%' + @pTicketNo + '%' 
          --and r.DeliverNo like  '%%' + @pDeliveryNo + '%' 
Return
END
ALTER PROCEDURE [dbo].[stp_student_Select] 
                @pVendorID as int, 
                @pCompanyID as int,
                @pAgingDate as int,
                @pTicketNo as VARCHAR(50),
                @pInvoiceNo as VARCHAR(50),
                @pDeliveryNo as VARCHAR(50),
                @pPartNo as VARCHAR(50)

As
SET NOCOUNT ON
BEGIN
    BEGIN TRY


            CREATE TABLE tempTable(
                    PartsReceivingID INT, 
                    SoPartID INT,
                    RecvQty INT,
                    ReturnQty INT
                    )
    ===============================================
    do something with tempTable
    ===============================================
        SELECT 
               isnull(r.Ticketid,0) AS TicketID,
               --i.TicketNo,
               r.SoPartNo  AS PartNo ,
               p.Description,
               r.InvoiceNo as InvoiceNo,
               --r.DeliveryNo,
               r.InvoiceDate AS InvoiceDate,
               DATEDIFF(DY,r.InvoiceDate,GETDATE())as Aging,
               r.Qty AS CurrentInventory,              
               t.ReturnQty AS ReturnQty

        FROM tempTable AS t,
             Parts.PartsReceiving AS r,
             --Ticket.TicketInfo as i,
             Parts.PartsInfo as p

        WHERE t.PartsReceivingID = r.PartsReceivingID
          --and i.TicketID = r.TicketID 
          and p.PartID = r.SoPartID  
          and t.ReturnQty >0 
          and DATEDIFF(DY,r.InvoiceDate,GETDATE()) > @pAgingDate
          and r.VendorID = @pVendorID 
          and r.CompanyID = @pCompanyID
          and r.SoPartNo like  '%%' + @pTicketNo + '%' 
          and r.InvoiceNo like  '%%' + @pInvoiceNo + '%' 
          and r.SoPartNo like  '%%' + @pPartNo + '%' 
          --and i.TicketNo like  '%%' + @pTicketNo + '%' 
          --and r.DeliverNo like  '%%' + @pDeliveryNo + '%' 


        DROP TABLE temptable
    END TRY

    BEGIN CATCH
        SELECT ERROR_MESSAGE() as ErrorMessge,
               ERROR_NUMBER() AS ErrorNumber
    END CATCH
Return
END
无工作版本存储过程

ALTER  PROCEDURE [dbo].[stp_student_Select_New] 
                @pSchID as int, 
                @pCompanyID as int,
                @pAgingDate as int,
                @pTicketNo as VARCHAR(50),
                @pInvoiceNo as VARCHAR(50),
                @pDeliveryNo as VARCHAR(50),
                @pPartNo as VARCHAR(50)
As
SET NOCOUNT ON
BEGIN
          SELECT @RowCount = count(*)
          FROM Parts.studentTempTable

        IF @RowCount > 0
        BEGIN
            TRUNCATE TABLE Parts.studentTempTable;
        END


    ===============================================
    do something with studentTempTable
    ===============================================

        SELECT 
               r.Ticketid AS TicketID,
               r.SoPartNo  AS PartNo ,
               p.Description,
               r.InvoiceNo as InvoiceNo,
               r.InvoiceDate AS InvoiceDate,
               DATEDIFF(DY,r.InvoiceDate,GETDATE())as Aging,
               r.Qty AS CurrentInventory,              
               t.ReturnQty AS ReturnQty
        FROM Parts.studentTempTable AS t,
             Parts.PartsReceiving AS r,
             Parts.PartsInfo as p
        WHERE t.PartsReceivingID = r.PartsReceivingID
          --and i.TicketID = r.TicketID 
          and p.PartID = r.SoPartID  
          and t.ReturnQty >0 
          and DATEDIFF(DY,r.InvoiceDate,GETDATE()) > @pAgingDate
          and r.SchID = @pSchID 
          and r.CompanyID = @pCompanyID
          and r.SoPartNo like  '%%' + @pTicketNo + '%' 
          and r.InvoiceNo like  '%%' + @pInvoiceNo + '%' 
          and r.SoPartNo like  '%%' + @pPartNo + '%' 
          --and i.TicketNo like  '%%' + @pTicketNo + '%' 
          --and r.DeliverNo like  '%%' + @pDeliveryNo + '%' 
Return
END
ALTER PROCEDURE [dbo].[stp_student_Select] 
                @pVendorID as int, 
                @pCompanyID as int,
                @pAgingDate as int,
                @pTicketNo as VARCHAR(50),
                @pInvoiceNo as VARCHAR(50),
                @pDeliveryNo as VARCHAR(50),
                @pPartNo as VARCHAR(50)

As
SET NOCOUNT ON
BEGIN
    BEGIN TRY


            CREATE TABLE tempTable(
                    PartsReceivingID INT, 
                    SoPartID INT,
                    RecvQty INT,
                    ReturnQty INT
                    )
    ===============================================
    do something with tempTable
    ===============================================
        SELECT 
               isnull(r.Ticketid,0) AS TicketID,
               --i.TicketNo,
               r.SoPartNo  AS PartNo ,
               p.Description,
               r.InvoiceNo as InvoiceNo,
               --r.DeliveryNo,
               r.InvoiceDate AS InvoiceDate,
               DATEDIFF(DY,r.InvoiceDate,GETDATE())as Aging,
               r.Qty AS CurrentInventory,              
               t.ReturnQty AS ReturnQty

        FROM tempTable AS t,
             Parts.PartsReceiving AS r,
             --Ticket.TicketInfo as i,
             Parts.PartsInfo as p

        WHERE t.PartsReceivingID = r.PartsReceivingID
          --and i.TicketID = r.TicketID 
          and p.PartID = r.SoPartID  
          and t.ReturnQty >0 
          and DATEDIFF(DY,r.InvoiceDate,GETDATE()) > @pAgingDate
          and r.VendorID = @pVendorID 
          and r.CompanyID = @pCompanyID
          and r.SoPartNo like  '%%' + @pTicketNo + '%' 
          and r.InvoiceNo like  '%%' + @pInvoiceNo + '%' 
          and r.SoPartNo like  '%%' + @pPartNo + '%' 
          --and i.TicketNo like  '%%' + @pTicketNo + '%' 
          --and r.DeliverNo like  '%%' + @pDeliveryNo + '%' 


        DROP TABLE temptable
    END TRY

    BEGIN CATCH
        SELECT ERROR_MESSAGE() as ErrorMessge,
               ERROR_NUMBER() AS ErrorNumber
    END CATCH
Return
END

如果在SSMS或Visual Studio中单独运行该过程,它是否返回结果?不管答案如何,我建议您使用一个表变量-您当前使用的不是临时表-它只是一个表。使用表变量将排除实际创建/删除表时出现的任何问题。谷歌搜索将为您提供大量信息,但这似乎是非常有用的:

如果诱惑真的是诱惑,那么要为存储过程的结果集自动生成类,您必须在存储过程定义的开头编写

IF(1=2)
BEGIN
SELECT
  CAST(NULL AS BIGINT)  AS TicketID --assuming TicketId is of bigint type 
  CAST(NULL AS NVARCHAR(16) AS PartNo --assuming PartNo is of Nvarchar(16)
  .......

  END

将sp中使用的临时表创建为原始数据库中的表,然后在sp中使用这些表。在dbml文件中删除sp后,它将返回sp的返回类型。在dbml中删除sp后,将原始sp更改为原来的状态,并在声明表变量时从原始数据库中删除临时表,我曾经有过这样的情况:由于缺乏统计数据,表变量的性能非常糟糕

在那些时候,我不得不回到创建一个简单的包装器或垫片存储过程的老路上来,它只调用真正的存储过程。包装器存储过程的一个工作要求是声明一个与实际存储过程的输出匹配的表变量,并执行INSERT…EXEC

Declare @Temp table (ColumnA int, ColumnB varchar(256))
Insert Into @Temp(ColumnA, ColumnB)
Exec dbo.OtherStoredProcedure /* pass needed parameters, if any */

Select ColumnA, ColumnB From @Temp
当然,临时表的定义必须与存储过程的输出完全匹配。你甚至不能退出专栏


LINQ to SQL此时不会计算子存储过程,您可以通过LINQ to SQL调用包装器存储过程。

在SP开头添加以下脚本

IF 1=0 BEGIN
    SET FMTONLY OFF
END
FMTONLY仅将元数据返回到数据集。可用于测试响应的格式,而无需实际运行查询

上面的查询将给出不带数据的列输出


来源:

你能发布你的存储过程的工作版本和非工作版本吗?谢谢你的评论,我附上存储过程的东西。顺便说一句,真正的temp表是在tempdb数据库中创建的,并用前面的一个或两个磅符号命名,如mytentable。它们通常是通过从一个或多个现有表中选择来创建的,如:select*into MyTestable from MyTable谢谢。我在LINQ实现中使用了临时表,这让人很困惑,为什么存储过程的heck数据类型无法确定。表变量工作正常。所以我不会否决这个答案,我已经开始看到很多人建议在搜索另一个答案时使用表变量而不是临时表,但这会对性能产生一些非常实际的影响,不应该被认为是所有情况下的解决方案,特别是如果表变量有任何较大的影响里面有大量的数据。@马特,你能在这里详述你的担忧吗?table变量的建议主要是由OP在创建表时的错误引起的,他似乎想要一些临时的东西。我的研究表明,在看到任何真正的性能差异之前,您需要一个足够大的数据集,以便从索引中获益。基于这个问题,这种担忧似乎是。。。超出范围。如果您觉得应该对性能提出警告,请随时在答案中添加细节。@jlnorsworthy这里有一个很好的讨论。对于小数据,您可能不会注意到太多,但SQL optimizer check在许多情况下使用临时表会比使用表变量更好,并且表变量没有建立在它们之上的统计信息,因此即使在小数据子集中,如果加入复杂查询,您也可以看到使用临时表的好处。