8

我在SQL Server 2008中有一個叫做'GetPrices'的存儲過程,它帶有一個名爲'StoreIDs'的表值參數。存儲過程中的表值參數和實體框架4.0

這是我爲這個TVP創建的類型:

CREATE TYPE integer_list_tbltype AS TABLE (n int) 

我想從我的實體框架調用SP。但是,當我嘗試將存儲過程添加到EDM時,出現以下錯誤:

函數'GetPrices'在參數索引2處有一個參數'StoreIDs',其數據類型'表類型'不是支持的。該功能被排除在外。

這有什麼解決方法嗎?有什麼想法嗎?

法比奧

回答

1

由於您無法使用表格參數,因此請嘗試傳入CSV sting,並讓存儲過程將其拆分成行。

有很多方法可以在SQL Server中拆分字符串。本文介紹了幾乎每一個方法的優點和缺點:

"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog

你需要創建一個分裂的功能。這是一個分裂的功能如何使用:

SELECT 
    * 
    FROM YourTable        y 
    INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value 

I prefer the number table approach to split a string in TSQL但也有許多方法來拆分在SQL Server中的字符串,見前面的鏈接,這說明各的優點和缺點。

對於數字表的方法來工作,你需要做的這一次表的設置,這將創建一個包含從1到10000行的表Numbers

SELECT TOP 10000 IDENTITY(int,1,1) AS Number 
    INTO Numbers 
    FROM sys.objects s1 
    CROSS JOIN sys.objects s2 
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) 

一旦Numbers表格設置,創建此分割功能:

CREATE FUNCTION [dbo].[FN_ListToTable] 
(
    @SplitOn char(1)  --REQUIRED, the character to split the @List string on 
    ,@List  varchar(8000)--REQUIRED, the list to split apart 
) 
RETURNS TABLE 
AS 
RETURN 
( ---------------- 
    --SINGLE QUERY-- --this will not return empty rows 
    ---------------- 
    SELECT 
     ListValue 
     FROM (SELECT 
        LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue 
        FROM (
          SELECT @SplitOn + @List + @SplitOn AS List2 
         ) AS dt 
         INNER JOIN Numbers n ON n.Number < LEN(dt.List2) 
        WHERE SUBSTRING(List2, number, 1) = @SplitOn 
      ) dt2 
     WHERE ListValue IS NOT NULL AND ListValue!='' 
); 
GO 

您現在可以輕鬆地拆分CSV字符串轉換成表格和加入或使用它,但是你需要:

CREATE PROCEDURE YourProcedure 
(
    @CSV_Param varchar(1000) 
) 
AS 

--just an example of what you can do 
UPDATE t 
    SET Col1=... 
    FROM dbo.FN_ListToTable(',',@CSV_Param) dt 
     INNER JOIN TBL_USERS     t ON CAST(dt.value AS INT)=t.id 

GO 
1

您可以使用ObjectContext.Connection屬性use ADO.NET來創建和使用您的表值參數。這可能是不可接受的,但如果你想使用這個令人敬畏的SQL Server 2008功能和EF,這似乎是你只是選擇。

然後,您可以選擇使用方法擴展部分生成的對象上下文,以照顧所有低級ADO.NET內容。像這樣:

public partial class FriendsOnBoardEntities : ObjectContext 
{ 
    public IList<int> GetPrices(int n) 
    { 
     // 'low-level' ado.net stuff here. 
     // Use SqlParameters, SqlCommand and what not... 
    } 
} 
1

我同意在這種情況下傳遞CSV sting是最好的解決方案。 我想建議更簡單的方法來分割csv字符串,而不用創建表格和函數,通過使用CTE:

declare @separator char(1); 
set @separator = ','; 

;with baseCte as 
(select left(@ValueList, charindex(@separator, @ValueList) - 1) as Value, 
substring(@ValueList, charindex(@separator, @ValueList) + 1, len(@ValueList)) 
as rest 
union all 
select left(rest, charindex(@separator, rest) - 1) as Value, 
substring(rest, charindex(@separator, rest) + 1, len(rest)) from baseCte 
where len(rest) > 1 
) 
select Value from baseCte 
OPTION (MAXRECURSION 0);