Как передать List <Int>в хранимую процедуру SQL Server - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть этот тип таблицы пользователя в SQL Server:

CREATE TYPE [dbo].[ListNew] AS TABLE
                               (
                                    [Id] [int] NOT NULL,
                                    PRIMARY KEY CLUSTERED ([Id] ASC) WITH (IGNORE_DUP_KEY = OFF)
                               )
GO

И использовать этот тип в параметре хранимой процедуры:

....
    (@lstNew ListNew READONLY,
     @UserName nvarchar(128))
AS
....

И использовать эту хранимую процедуру в ASP.NET MVCс этим кодом:

List<int> lstNew = MyList.Select(o => o.Key).ToList();
List<XXXView> lstView = db.Database.SqlQuery<XXXView>("MyStoredProcedure @lstNew,@UserName",
              new SqlParameter("@lstNew", lstNew),
              new SqlParameter("@UserName", userName)).ToList();

, но он не работает, и получите эту ошибку:

Нет сопоставления для типа объекта System.Collections.Generic.List`1 [[System.Int32, mscorlib, Версия = 4.0.0.0, Культура = нейтральная, PublicKeyToken = b77a5c561934e089]] для известного типа управляемого управляемого провайдера.

Я пытаюсь без ListNew и использую только имя пользователя, он работает


Редактировать:

Я использую этот код:

myParameter.SqlDbType = SqlDbType.Udt;
myParameter.UdtTypeName = "ListNew";

Но я получаю то же предупреждение

Ответы [ 3 ]

0 голосов
/ 18 декабря 2018

Я всегда использую XML для передачи этих типов данных в sqlserver sproc.

Когда вы передаете свой XML в sproc, вы можете использовать что-то вроде этого, чтобы иметь его в качестве таблицы в вашем sproc:

(закомментированные строки - это структура моего XML. Управляйте ею для собственного использования.)

EXEC sp_xml_preparedocument @XmlHandle output,@FieldPermissionAccessXML
    --'<FieldPermissions>
    --<FieldPermission FieldName="" RoleID="1" Access="1" />
    --<FieldPermission FieldName="" RoleID="2" Access="1" />'
    --select * from JMP_FieldPermissions
INSERT INTO #FieldPermissionsTable 
SELECT *--ID,Value, Value2, Navi_User 
FROM  OPENXML (@XmlHandle, './Row_ID/Elements') 
      WITH (TE_ID VARCHAR(MAX) '@ID',
    Value VARCHAR(MAX) '@Value',
    Value2 VARCHAR(MAX) '@Value2',
    NAVI_USER VARCHAR(MAX) '@Navi_User'     
            )
0 голосов
/ 18 декабря 2018

Это решенная проблема и надлежащим образом задокументированная документация.

Вам нужно будет определить таблицу на стороне сервера, а затем передать параметр с табличным значением.

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/table-valued-parameters

Это сводится к использованию структурированного SqlDbType.

// Configure the command and parameter.  
SqlCommand insertCommand = new SqlCommand(sqlInsert, connection);  
SqlParameter tvpParam = insertCommand.Parameters.AddWithValue("@tvpNewCategories", addedCategories);  
tvpParam.SqlDbType = SqlDbType.Structured;  
tvpParam.TypeName = "dbo.CategoryTableType";

Вы МОЖЕТЕ использовать DataTable, но затем вы вводите наиболее затратный подход из возможных в качестве объектной модели - или вы простоиспользуйте ...

https://forums.asp.net/t/1845039.aspx?Table+Value+Parameter+Use+With+C+without+using+DataTable

По сути, вы преобразуете свои данные в SqlDataRecords и передаете их. Нужны некоторые метаданные - но, как правило, это может быть обобщено и помещается под страницей кода.Ссылка содержит код (который я не могу скопировать здесь, потому что - ну, это не МОЙ код).

0 голосов
/ 18 декабря 2018

Вы не можете передать какой-либо общий список типов в качестве параметра SP, необходимо передать его как DataTable вместо List.Вот пример:

DataTable mappingTbl = ListToDataTable(mappingData);

SqlConnection con = new SqlConnection(conStr);
            con.Open();
            SqlCommand cmd = new SqlCommand(StoredProcedure.GetSavedFormList, con);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("@UDT_EBFromMappingTable", mappingTbl);


public DataTable ListToDataTable<T>(List<T> items)
        {
            DataTable dataTable = new DataTable(typeof(T).Name);

            //Get all the properties
            PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (PropertyInfo prop in Props)
            {
                //Defining type of data column gives proper data table 
                var type = (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) ? Nullable.GetUnderlyingType(prop.PropertyType) : prop.PropertyType);
                //Setting column names as Property names
                dataTable.Columns.Add(prop.Name, type);
            }

            foreach (T item in items)
            {
                var values = new object[Props.Length];
                for (int i = 0; i < Props.Length; i++)
                {
                    //inserting property values to datatable rows
                    values[i] = Props[i].GetValue(item, null);
                }
                dataTable.Rows.Add(values);
            }
            //put a breakpoint here and check datatable
            return dataTable;
        }

Пусть это вам поможет.:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...