13

mam parametr wycenione tabela w SQL Server 2012 zdefiniowany jako:Przekazywanie parametru typu „obiektu” w parametrze wycenione tabela dla sql_variant kolumny

CREATE TYPE [dbo].[TVP] AS TABLE (
    [Id] [int] NOT NULL, 
    [FieldName] [nvarchar](100) NOT NULL, 
    [Value] [sql_variant] NOT NULL 
) 

nazywam go w C# z kodem, który wygląda mniej więcej tak następujące:

var mdItems = new DataTable(); 
mdItems.Columns.Add("Id", typeof(int)); 
mdItems.Columns.Add("FieldName", typeof(string)); 
mdItems.Columns.Add("Value", typeof(object)); 
mdItems.Rows.Add(new object[] {2, "blah", "value"}); //'value' is usually a string 
SqlCommand sqlCommand = conn.CreateCommand(); 
sqlCommand.CommandText = "[WriteFieldValues]"; 
sqlCommand.CommandType = CommandType.StoredProcedure; 
sqlCommand.Parameters.AddWithValue("@FieldValues", mdItems); 
sqlCommand.ExecuteNonQuery(); 

I wtedy pojawia się następujący błąd z SQL Server na wezwanie ExecuteNonQuery:

Typ kolumny "Wartość" nie jest obsługiwany. Typ jest „Przedmiot”

znalazłem someone który napotkał ten sam problem 3 lata temu, kiedy został on zidentyfikowany jako znany Microsoft błędu. Jednak link do błędu jest zepsuty. Czy ktoś wie, czy istnieją aktualne informacje na temat statusu błędu lub potencjalnego obejścia? W obecnej wersji ten błąd naprawdę zabija wartość pól sql_variant.

+0

@JonSeigel Dodałem kod wywołujący C#. – Dan

+0

z jakiego powodu wybrałeś 'sql_variant'? Po prostu ciekawy. – codingbiz

+0

@ codingbiz W polu należy zapisać ciąg, datę i wartości numeryczne. Mogę wykonywać ręczne konwersje w kodzie, ale to właśnie powinien zrobić dla mnie sql_variant. – Dan

Odpowiedz

1

Mam nadzieję, że naprawdę dobrze wykorzystasz ten model danych "jeden rozmiar dla wszystkich". Zazwyczaj wysadza się w twarz podczas próby skalowania z powodu nieporozumienia opartej na zestawie algebry relacyjnej i sargeability. Może podjąłeś tę myśl? Nie chciałbym opracowywać ETL-ów ani raportów dotyczących tego modelu.

Należy pamiętać, że próbujesz wstawić obiekt do silnika bazy danych, który nie ma wiedzy o podstawowej strukturze. Obiekt jest tak ogólny, że odbiorca obiektu nie ma wiedzy na temat jego interpretacji. Obiekt ma właściwości, ale będziesz mieć do nich dostęp tylko wtedy, gdy posiadasz wyraźne instrukcje lub używasz odbicia, aby zidentyfikować typ bazowy, aby rozpakować je. Jedynym sposobem (o którym wiem), aby niezawodnie przekonwertować obiekt na ukryty typ, nie wiedząc nic na ten temat, jest użycie refleksji. Może niektórzy guru .Net będą mnie wypełniać na inne sposoby.

Typowy typ obiektu nie może być przechowywany w takiej postaci sql_variant. Nawet sql_variant wymaga nieco mocno wpisanych wartości. SQL Server nie będzie domyślnie korzystać z odbicia, aby spróbować dowiedzieć się, jaki jest typ danych (a następnie wartość podstawowych danych).

Można użyć metody GetType System.Reflection, a następnie wyrzucić instrukcję case, aby odlać odpowiednio przed wstawieniem.

+0

Ta funkcja TVP i proc znajduje się na obrzeżach mojego modelu danych i nie znajduje się w obszarze o dużej wydajności lub wymagającym intensywnego wyszukiwania. W tym konkretnym przypadku chciałem, aby SQL Server zarządzał dla mnie typami konwersji, a nie własnymi. – Dan

0

Niestety, nie mam teraz czasu, aby w pełni odpowiedzieć na to pytanie, ale mogę wprowadzić cię na właściwą drogę.

To, co zrobiłem w przeszłości, zamiast używać TVP, użyj parametru XML, serializuj zbiór danych (lub jakikolwiek POCO, o to chodzi) jako XML, przekaż ten XML do proc, następnie użyj " .nodes "właściwość (i inni członkowie) zmiennej xml, aby wyodrębnić wszystko, co było potrzebne w tabelach tymczasowych, lokalnych tablicach vars," tabelach roboczych "itd.

To mało precyzyjne, ale jeśli serializuje się ten zestaw danych i sprawdza utworzony xml i odczytywany w XML Data Types w Books On Line, najprawdopodobniej będziesz w stanie dowiedzieć się, jak wykonać swoje zadanie.

Jeśli to nie pomoże, postaram się przygotować jutro właściwe rozwiązanie, ponieważ właśnie natknąłem się na to pytanie, gdy wyjeżdżałem na cały dzień.

Pozdrawiam!