8

Tengo un procedimiento almacenado en SQL Server 2008 llamado 'GetPrices' con un parámetro de valor de tabla llamado 'StoreIDs'.Parámetro con valores de tabla en el procedimiento almacenado y Entity Framework 4.0

Este es el tipo que he creado para este TVP:

CREATE TYPE integer_list_tbltype AS TABLE (n int) 

quisiera llamar al SP de mi marco de la entidad. Pero cuando intento agregar el Procedimiento almacenado al EDM, aparece el siguiente error:

La función 'GetPrices' tiene un parámetro 'StoreIDs' en el parámetro índice 2 que tiene un tipo de datos 'tipo de tabla' que no es soportado. La función fue excluida.

¿Hay alguna solución para esto? ¿Alguna idea?

Fabio

Respuesta

1

Dado que no puede utilizar un parámetro de tabla, intente pasar un Stre stv y haga que el procedimiento almacenado lo divida en filas.

Hay muchas formas de dividir cadenas en SQL Server. Este artículo cubre los pros y los contras de casi todos los métodos:

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

Es necesario crear una función de división. Se trata de cómo se puede utilizar una función de división:

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 pero hay numerosas maneras de dividir cadenas en SQL Server, consulte el enlace anterior, lo que explica las ventajas y desventajas de cada uno.

Para el método Números mesa de trabajo, lo que necesita hacer esta configuración de la tabla una vez, lo que creará una mesa Numbers que contiene filas de 1 a 10.000:

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) 

Una vez que la tabla Números está configurado , crear esta función de división:

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 

ahora puede fácilmente dividir una cadena CSV en una mesa y unirse en él o utilizarlo sin embargo es necesario:

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

Puede usar la propiedad ObjectContext.Connection en use ADO.NET para crear y usar los parámetros con valores de tabla. Puede que esto no sea aceptable, pero si desea utilizar esta increíble característica de SQL Server 2008 y EF, parece ser que usted es el único elegido.

Puede elegir ampliar el contexto del objeto parcialmente generado con el método para ocuparse de todas las cosas de bajo nivel de ADO.NET.De esta manera:

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

Estoy de acuerdo en que pasar una picadura de CSV es la mejor solución en este caso. Me gustaría proponer una forma más simple para dividir cadenas de CSV, sin crear tablas y funciones, mediante el uso de 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); 
Cuestiones relacionadas