2009-02-26 9 views
31

Ho ottenuto il seguente stored procedureCome si può denominare le tabelle del set di dati che si restituiscono in un processo memorizzato?

Create procedure psfoo() 
AS 
select * from tbA 
select * from tbB 

che sto quindi l'accesso ai dati in questo modo:

 Sql Command mySqlCommand = new SqlCommand("psfoo" , DbConnection) 
    DataSet ds = new DataSet(); 
    mySqlCommand.CommandType = CommandType.StoredProcedure; 
    SqlDataAdapter mySqlDataAdapter = new SqlDataAdapter(); 
    mySqlDataAdapter.SelectCommand = mySqlCommand; 
    mySqlDataAdapter.Fill(ds); 

Ora, quando ho voglia di accedere alle mie tabelle, devo fare questo:

 DataTable datatableA = ds.Tables[0]; 
    DataTable datatableB = ds.Tables[1]; 

la proprietà set di dati tabelle anche avuto una funzione di accesso da stringa (invece di int).

E 'possibile quindi specificare il nome delle tabelle nel codice SQL, in modo che possa invece scrivere questo:

 DataTable datatableA = ds.Tables["NametbA"]; 
    DataTable datatableB = ds.Tables["NametbB"]; 

sto usando SQL Server 2008, se questo fa la differenza.

+3

Ottima domanda. Peccato che dalle risposte, sembra che questo non sia realmente possibile. Sarebbe una buona caratteristica poter fornire un alias a una query in una procedura e utilizzarla come TableName per il DataTable risultante. Fa schifo dover fare affidamento sull'ordine in cui le query vengono eseguite all'interno della procedura, dal momento che qualcuno potrebbe modificare la procedura in futuro e interrompere involontariamente il codice. – Jim

+0

@Jim vedi la risposta di Ramzan. Oltre a far sì che Microsoft aggiunga la possibilità di denominare tabelle da SP, questa sembra la strada da percorrere, soprattutto se si sta eseguendo il wrapping del codice di accesso ai dati in una classe di utilità come fa la mia squadra. –

risposta

28

Per quanto ne so, dal proc memorizzato, non è possibile farlo. Tuttavia, è possibile impostare i nomi una volta recuperato il DataSet e quindi utilizzarli da quel momento in poi.

ds.Tables[0].TableName = "NametbA"; 
+0

Grazie, non potevo essere disturbato aprendo VS :) –

5

C'è qualche motivo non è possibile nominare manualmente dopo aver riempito il DataSet?

mySqlDataAdapter.Fill(ds); 
ds.Tables[0].TableName = "NametbA"; 
ds.Tables[1].TableName = "NametbB"; 

Io non conosco alcun modo dare un nome alle DataTable che vengono restituiti come parte di più set di risultati da una stored procedure, ma se si sa cosa il proc memorizzato sta tornando poi nominare manualmente dovrebbero funzionare bene .

Modifica

Sapendo che si ha il controllo della stored procedure, un'alternativa potrebbe essere quella di aggiungere una colonna per il set di risultati che rappresenta il nome della tabella. Allora si potrebbe essere in grado di fare qualcosa di simile:

foreach (DataTable table in ds.Tables) 
{ 
    table.TableName = table.Rows[0]["TableName"].ToString(); 
} 

Tuttavia, questo si basa sui set di risultati di ritorno dalla stored procedure in realtà contenenti righe. Se non contengono righe, dovresti racchiuderlo in un'istruzione "if" e non tutte le tabelle otterrebbero un nome.

+0

Sì. Sto pensando di scrivere un processo memorizzato che non restituisce sempre le stesse tabelle, a seconda dell'elevazione dell'utente. Poiché le tabelle restituite possono variare, desidero accedervi utilizzando un nome sicuro piuttosto che un indice. – Brann

+2

La mia soluzione alternativa è di restituire segnaposti vuoti in modo che possa fare affidamento sull'indice. ( – Brann

+0

Sì, restituendo tabelle "segnaposto" tra ogni set di risultati "reale" per dare il prossimo un nome potrebbe essere l'unica soluzione, ma sono d'accordo che sembra un po 'brutto –

0

Questo funziona per me, ma ha bisogno di qualche lavoro in più per ottenere i nomi delle tabelle attesi:

Dim tableCount As Integer = 3 
    Dim tables(tableCount) As DataTable 
    tables(0) = (New DataTable("Employee")) 
    tables(1) = (New DataTable("Manager")) 
    tables(2) = (New DataTable("Department")) 
    dsUControlData.Tables.Add(tables(0)) 
    dsUControlData.Tables.Add(tables(1)) 
    dsUControlData.Tables.Add(tables(2)) 

    'Fill required tables 
    da.Fill(0, 0, tables) 

    Return dsUControlData 
2

buona idea, la sua migliore la vostra procedura restituisce tre di risultati, invece di aggiungere il nome della tabella su

firs trow of each table 
select 'tbA' FirstTableName,'tbB' SecondTableName 
select * from tbA 
select * from tbB 

ogni volta che si esegue la procedura le tabelle [0] avranno una riga che continua a continuare a selezionare i nomi delle tabelle

Un'altra idea può essere passare il nome della tabella come outpu t paramter di procedura

Create procedure psfoo (@tb1 varchar(50) output,@tb2 varchar(50) output) 
AS 
set @tb1='tbA' 
set @tb2 'tbB' 
select * from tbA 
select * from tbB 

se questo metodo si limita e seleziona sono variabili è possibile creare procedura come questa

Create procedure psfoo() 
    AS 
    select * from tbA 
    select * from tbB 
return 'tbA,tbB' 

e dalla procedura di splitting valore retrun in string [] è possibile ottenere il nome di tavoli ordinally

[email protected](new char[]{','}); 
string tablenam1=returnvalue[0]; 
string tablenam2=returnvalue[1]; 
+0

Le risposte proposte qui tutte per il codice C# per essere generiche e accettare qualsiasi stored procedure.Questo esattamente quello che stavo cercando! – JoeFletch

+1

Per quanto posso dire 'return 'tbA, tbB'' non funzionerà dato che una stored procedure SQL Server può restituire un intero solo nell'istruzione return [MSDN Article] (http://msdn.microsoft.com/en-us/library/ms174998. Aspx) Quindi penso che la variabile di output è probabilmente la soluzione per me! – JoeFletch

0

Si potrebbe restituire un set di risultati in più che i nomi delle tabelle come questo:

SELECT 'firstTableName' AS tbl 
UNION 
SELECT 'secondTableName' AS tbl 
UNION 
... 

Se quello era il primo set di risultati, è possibile utilizzarlo per denominare i set di risultati successivi man mano che si procede.

0

Ho un proc memorizzato che accede a tutti i dati nella mia impresa e restituisce più set di risultati. Ha più senso per me fare una selezione con il nome prima di ogni serie di risultati. Come così:

SELECT 'Customers' AS TableName 
SELECT ID, Name FROM dbo.Customer 
SELECT 'Orders' AS TableName 
SELECT ID, Created FROM dbo.[Order] 

Poi, quando ho iterare MyDataSet.Tables, ho solo il un loop e la logica di ricerca diretto. Non esiste una tabella di metadati principale per tenere il passo. Funziona anche quando non viene restituita alcuna tabella. Se i dati della tabella non vengono restituiti, i metadati corrispondenti non vengono restituiti, il che ha senso per me.

For Each DataTable As DataTable In MyDataSet.Tables 
    MyDataSet.Tables(MyDataSet.Tables.IndexOf(DataTable) + 1).TableName = DataTable.Rows(0)("TableName") 
Next 

Se voglio aggiungere più colonne alle tabelle dei meta-dati, posso. Procedura

6

Stored:

select 'tbA','tbB','tbC' 
    select * from tbA 
    select * from tbB 
    select * from tbC 

front-end:

 int i = 1; 
     foreach (string tablename in dsEmailData.Tables[0].Rows[0][0].ToString().Split(',')) 
     { 
      dsEmailData.Tables[i++].TableName = tablename; 
     } 

Spero che questo aiuti

0

So che questo è un post molto vecchio, ma per rispondere a ... Sì, è possibile. basta aggiungere il "TableName" nel dataadapter Fill chiamata ..

MyDataAdapter.Fill(ds, "TableName"); 

Sono un C# ragazzo, ma si ottiene il punto.

+0

Questo potrebbe rompere la transazione in costolette, una cosa che è necessario evitare. La ragione per cui ha posto la domanda è che vuole tenerlo in una transazione n, penso. –

0

So che questa è una vecchia domanda, ma stavo pensando di fare le stesse cose oggi, quindi non stavo semplicemente collegando un indice del set di risultati. Perché se la procedura memorizzata cambia in ordine di selezione del codice .net sarebbe bomba.

Mi è venuta la soluzione di aggiungere una colonna al set di risultati con il nome della tabella e utilizzando un'istruzione case per vedere se la colonna esiste nella tabella. Ma sembrava che stavo spostando il codice. Ho appena creato l'SQL statico. Inoltre, cosa succede se si dispone di una colonna denominata la stessa in una tabella diversa. Lame ...

myDS.Tables(i).Columns.Contains("TableName") 
-1

può essere questo potrebbe essere il lavoro intorno

Create procedure psfoo() 
AS 
select * ,'tbA' as TableName from tbA 
select * ,'tbB' as TableName from tbB 

Poi nel codice C#

 foreach (DataTable dt in ds.Tables) 
     { 
      if (dt.Rows[0]["TableName"].ToString().Contains("tbA")) 
      { 

      } 
      else if (dt.Rows[0]["TableName"].ToString().Contains("tbB")) 
      { 

      } 
     } 
1

Al fine di dare i nomi a tutti tabella in un set di dati, abbiamo bisogno di scrivere un'altra query di selezione all'ultimo SP o T-Sql.

lsqry = New System.Text.StringBuilder 
lsqry.AppendLine("select * from Bill_main") 
lsqry.AppendLine("select * from serviceonly") 
lsqry.AppendLine("select * from PendingService") 
lsqry.AppendLine("select * from T_servicebillhd") 
lsqry.AppendLine("select 'Bill_Main','serviceonly','PendingService','T_servicebillhd'") 

Using con As New SqlConnection(lsConnection) 
    Try 
     con.Open() 
     Using cmd As SqlCommand = con.CreateCommand 
      With cmd 
       .CommandText = lsqry.ToString 
       .CommandType = CommandType.Text 
      End With 
      Using da As New SqlDataAdapter(cmd) 
       da.Fill(DS) 
      End Using 
     End Using 

     For li As Integer = 0 To DS.Tables.Count - 2 
      DS.Tables(li).TableName = DS.Tables(DS.Tables.Count - 1).Rows(0).Item(li) 
     Next 
    Catch ex As Exception 

    End Try 
End Using 

Nell'esempio di cui sopra, io sto usando istruzione T-SQL invece di SP. In cui ho scritto 4 query di selezione e l'ultimo è il nome di tabella di quelle tabelle. E recuperare l'ultima tabella che contiene i nomi delle tabelle e assegnarlo alla tabella utilizzando la proprietà TableName.

0

Si può provare questo:

aggiungere sotto la linea nella procedura

Select 'TableName1','TableName2'; 

con C#:

for (var i=0;i<ds.Tables[0].Columns.Count;i++) 
{ 
    ds.Tables[i + 1].TableName = ds.Tables[0].Columns[i].ColumnName; 

    } 
0

Prova questa

YourDataAdapter.Fill(ds, "Table"); 
0

Prova questa. In MS SQL 2008 R2, lo uso sempre.

mySqlDataAdapter.Fill(ds,"NameTableA"); 
0

dovrebbero utilizzare selezionare in "yourtablename" da originaltable, questo è solo un esempio, trovare la sintassi corretta di selezionare in dichiarazione.

Questo è il modo corretto di farlo per le vostre esigenze. Grazie.

0

Questa domanda è vecchia ma, è in cima alla ricerca su google, hehe. Forse aiuterà qualcuno ...

E la risposta è sì, è possibile specificare il nome delle tabelle nel codice in modo che sia possibile accedere a DataTable in DataSet per nome.

Prima di tutto, devo spiegare come funziona TableMapping. Se non specificiamo TableMappings con SqlDataAdapter (SqlDataAdapter che riempirà il nostro DataSet), per impostazione predefinita la prima tabella sarà denominata "Table", la seconda sarà denominata "Table1", la terza sarà denominata "Table2" ecc.

Così, quando vogliamo dare un nome DataTable nel DataSet, usiamo in questo modo:

//... 

System.Data.DataSet myDataSet = new System.Data.DataSet(); 

using (System.Data.SqlClient.SqlDataAdapter dbAdapter = new System.Data.SqlClient.SqlDataAdapter(dbCommand)) 
{ 
    dbAdapter.TableMappings.Add("Table", "MyFirstTitleForTableOne"); 
    dbAdapter.TableMappings.Add("Table1", "MyFirstTitleForTableTwo"); 
    dbAdapter.TableMappings.Add("Table2", "MyFirstTitleForTableThree"); 
    dbAdapter.TableMappings.Add("Table3", "MyFirstTitleForTableFour"); 
     //... 

    dbAdapter.Fill(myDataSet); 
} 

//... 

E, ora possiamo accedere DataTable per il nostro titolo:

System.Data.DataTable firstTable = myDataSet.Tables["MyFirstTitleForTableOne"]; 
System.Data.DataTable secondTable = myDataSet.Tables["MyFirstTitleForTableTwo"]; 

dispiace, ma io non ha scritto il codice che controlla il null (myDataSet) o lo imposta nel blocco try/catch perché penso che non sia irrilevante a questa domanda.

Problemi correlati