2011-09-30 11 views
10

Ho un UDT CLR che trarre grandi vantaggi da metodi con valori di tabella, ala xml.nodes():È possibile creare metodi * con valori tabella * in un tipo definito dall'utente CLR SQL?

-- nodes() example, for reference: 
declare @xml xml = '<id>1</id><id>2</id><id>5</id><id>10</id>' 
select c.value('.','int') as id from @xml.nodes('/id') t (c) 

Voglio qualcosa di simile per la mia UDT:

-- would return tuples (1, 4), (1, 5), (1, 6)....(1, 20) 
declare @udt dbo.FancyType = '1.4:20' 
select * from @udt.AsTable() t (c) 

Qualcuno ha qualche esperienza w/Questo? Qualsiasi aiuto sarebbe molto apprezzato. Ho provato alcune cose e hanno fallito tutte. Ho cercato documentazione ed esempi e non ne ho trovato.

Sì, so che potrei creare UDF con valori di tabella che prendono il mio UDT come parametro, ma speravo piuttosto di raggruppare tutto in un unico tipo, in stile OO.

EDIT

Russell Hart trovato the documentation states that table-valued methods are not supported, e fissato la mia sintassi per produrre l'errore di runtime previsto (vedi sotto).

In VS2010, dopo aver creato un nuovo UDT, ho aggiunto questo alla fine della definizione struct:

[SqlMethod(FillRowMethodName = "GetTable_FillRow", TableDefinition = "Id INT")] 
public IEnumerable GetTable() 
{ 
    ArrayList resultCollection = new ArrayList(); 
    resultCollection.Add(1); 
    resultCollection.Add(2); 
    resultCollection.Add(3); 
    return resultCollection; 
} 

public static void GetTable_FillRow(object tableResultObj, out SqlInt32 Id) 
{ 
    Id = (int)tableResultObj; 
} 

Questo costruisce e distribuisce con successo. Ma poi in SSMS, otteniamo un errore di runtime come previsto (se non parola per parola):

-- needed to alias the column in the SELECT clause, rather than after the table alias. 
declare @this dbo.tvm_example = '' 
select t.[Id] as [ID] from @this.GetTable() as [t] 

Msg 2715, Level 16, State 3, Line 2 
Column, parameter, or variable #1: Cannot find data type dbo.tvm_example. 
Parameter or variable '@this' has an invalid data type. 

Quindi, a quanto pare non è possibile, dopo tutto. E anche se fosse possibile, probabilmente non sarebbe saggio, date le restrizioni sulla modifica degli oggetti CLR in SQL Server.

Detto questo, se qualcuno conosce un trucco per aggirare questa particolare limitazione, aumenterò di conseguenza una nuova taglia.

risposta

6

Hai eseguito il alias della tabella ma non delle colonne. Provate,

declare @this dbo.tvm_example = '' 
select t.[Id] as [ID] from @this.GetTable() as [t] 

Secondo la documentazione, http://msdn.microsoft.com/en-us/library/ms131069(v=SQL.100).aspx#Y4739, questo dovesse fallire su un altro errore di runtime per quanto riguarda il tipo corretto.

La classe SqlMethodAttribute eredita dalla classe SqlFunctionAttribute, così SqlMethodAttribute eredita i campi FillRowMethodName e TableDefinition da SqlFunctionAttribute. Ciò implica che è possibile scrivere un metodo con valori di tabella, il che non è il caso. Il metodo compila e l'assembly viene distribuito, ma un errore sul tipo di ritorno IEnumerable viene generato in fase di esecuzione con il seguente messaggio: "Metodo, proprietà o campo '' in classe '' in assembly '' ha un tipo di ritorno non valido."

Possono evitare di supportare tale metodo. Se si modifica l'assembly con gli aggiornamenti del metodo, ciò può causare problemi ai dati nelle colonne UDT. Una soluzione appropriata è avere un UDT minimo, quindi una classe separata di metodi per accompagnarlo. Ciò garantirà flessibilità e metodi completi.

Il metodo dei nodi xml non cambia in modo che non sia soggetto alle stesse limitazioni di implementazione.

Spero che questo aiuti Peter e buona fortuna.

+0

Grazie Russ, sì aiuta. –