[英]How can you name the Dataset's Tables you return in a stored proc?
我有以下存儲過程
Create procedure psfoo ()
AS
select * from tbA
select * from tbB
然后我以這種方式訪問數據:
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);
現在,當我想訪問我的表時,我必須這樣做:
DataTable datatableA = ds.Tables[0];
DataTable datatableB = ds.Tables[1];
dataset Tables 屬性也通過字符串(而不是 int)獲得了訪問器。
是否可以在 SQL 代碼中指定表的名稱,以便我可以改為這樣寫:
DataTable datatableA = ds.Tables["NametbA"];
DataTable datatableB = ds.Tables["NametbB"];
我正在使用 SQL 服務器 2008,如果這有所不同的話。
據我所知,從存儲過程中,你不能這樣做。 但是,您可以在檢索到 DataSet 后設置名稱,然后從那時起使用它們。
ds.Tables[0].TableName = "NametbA";
存儲過程:
select 'tbA','tbB','tbC'
select * from tbA
select * from tbB
select * from tbC
前端:
int i = 1;
foreach (string tablename in dsEmailData.Tables[0].Rows[0][0].ToString().Split(','))
{
dsEmailData.Tables[i++].TableName = tablename;
}
希望這可以幫助
填充數據集后有什么原因不能手動命名它們嗎?
mySqlDataAdapter.Fill(ds);
ds.Tables[0].TableName = "NametbA";
ds.Tables[1].TableName = "NametbB";
我不知道有什么方法可以命名作為存儲過程的多個結果集的一部分返回的 DataTables,但是如果您知道存儲過程返回的內容,那么手動命名它們應該可以正常工作。
編輯
知道您可以控制存儲過程,一種替代方法可能是向結果集中添加一個表示表名的列。 然后,您可能可以執行以下操作:
foreach (DataTable table in ds.Tables)
{
table.TableName = table.Rows[0]["TableName"].ToString();
}
但是,這依賴於從實際包含行的存儲過程返回的結果集。 如果它們不包含行,那么您必須將其包裝在“if”語句中,並且並非每個表都會獲得名稱。
好主意,最好你的過程返回三個結果集而不是添加表名
firs trow of each table
select 'tbA' FirstTableName,'tbB' SecondTableName
select * from tbA
select * from tbB
每次執行過程時,表 [0] 都會有一行保持 select 表名
另一個想法可以將表名作為程序的 output 參數傳遞
Create procedure psfoo (@tb1 varchar(50) output,@tb2 varchar(50) output)
AS
set @tb1='tbA'
set @tb2 'tbB'
select * from tbA
select * from tbB
如果此方法限制您並且選擇是可變的,您可以創建這樣的過程
Create procedure psfoo ()
AS
select * from tbA
select * from tbB
return 'tbA,tbB'
並通過將過程 retrun 值拆分為 string[] 您可以按順序獲取表的名稱
returnvalue=@returnvaluefromSp.split(new char[]{','});
string tablenam1=returnvalue[0];
string tablenam2=returnvalue[1];
我有一個存儲過程,可以訪問我企業中的所有數據並返回多個結果集。 對我來說,在每個結果集之前使用名稱做一個 select 更有意義。 像這樣:
SELECT 'Customers' AS TableName
SELECT ID, Name FROM dbo.Customer
SELECT 'Orders' AS TableName
SELECT ID, Created FROM dbo.[Order]
然后,當我遍歷 MyDataSet.Tables 時,我只有一個循環和直截了當的查找邏輯。 沒有要跟上的主元數據表。 這甚至在沒有返回表的情況下也有效。 如果不返回表數據,則不返回匹配的元數據,這對我來說很有意義。
For Each DataTable As DataTable In MyDataSet.Tables
MyDataSet.Tables(MyDataSet.Tables.IndexOf(DataTable) + 1).TableName = DataTable.Rows(0)("TableName")
Next
如果我想向元數據表添加更多列,我可以。
為了給數據集中的所有表命名,我們需要在 SP 或 T-Sql 的最后再編寫一個 select 查詢。
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
在上面的示例中,我使用的是 t-sql 語句而不是 SP。 我在其中寫了 4 個 select 查詢,最后一個是這些表的表名。 並獲取包含表名稱的最后一個表,並使用 TableName 屬性將其分配給表。
這對我有用,但需要一些額外的工作來獲得預期的表名:
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
我知道這是一個非常古老的帖子,但要回答......是的,這是可能的。 只需在 dataadapter Fill
調用中添加"TableName"
。
MyDataAdapter.Fill(ds, "TableName");
我是 C# 人,但你明白了。
我知道這是一個老問題,但我今天正在考慮做同樣的事情,所以我不只是循環遍歷結果數據集的索引。 因為如果存儲過程按 select 的順序更改,則 .net 代碼將被炸毀。
我想出了用表名向結果集中添加一列並使用 case 語句查看表中是否存在該列的解決方案。 但似乎我在移動代碼。 剛剛制作了 SQL static。 另外,如果您在不同的表中有一個名稱相同的列怎么辦。 瘸...
myDS.Tables(i).Columns.Contains("TableName")
你可以試試這個:
在您的程序中添加以下行
Select 'TableName1','TableName2';
使用 C#:
for (var i=0;i<ds.Tables[0].Columns.Count;i++)
{
ds.Tables[i + 1].TableName = ds.Tables[0].Columns[i].ColumnName;
}
嘗試這個
YourDataAdapter.Fill(ds, "Table");
嘗試這個。 在 MS SQL 2008 R2 中,我總是使用它。
mySqlDataAdapter.Fill(ds,"NameTableA");
應該使用 select 從 originaltable 到 "yourtablename",這只是一個例子,找到正確的語法 select 到語句中。
這是滿足您要求的正確方法。 謝謝你。
這個問題是老問題了,但是,它在谷歌搜索的頂部,呵呵。 也許它會幫助某人......
答案是肯定的,可以在代碼中指定表的名稱,這樣就可以通過名稱訪問DataSet中的DataTable。
首先,我必須解釋一下 TableMapping 是如何工作的。 如果我們不使用 SqlDataAdapter 指定 TableMappings(SqlDataAdapter 將填充我們的 DataSet),那么默認情況下第一個表將命名為“Table”,第二個將命名為“Table1”,第三個將命名為“Table2”等。
因此,當我們想在 DataSet 中命名 DataTable 時,我們可以這樣使用它:
//...
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);
}
//...
而且,現在我們可以通過標題訪問 DataTable:
System.Data.DataTable firstTable = myDataSet.Tables["MyFirstTitleForTableOne"];
System.Data.DataTable secondTable = myDataSet.Tables["MyFirstTitleForTableTwo"];
抱歉,但我沒有編寫代碼來檢查 null (myDataSet) 或將其設置在 try/catch 塊中,因為我認為這與這個問題無關。
我知道這是舊帖子,但是當我的存儲過程返回多個數據集時,我也遇到了類似的情況,我不確定根據滿足的條件將返回多少個數據集。
因此,我實現了如下排序以按特定順序獲取返回數據集,這樣我也可以根據代碼端提供的條件在 C# 代碼上管理每個數據集。
if (dsop != null && dsop.ReturnDataSet != null && dsop.ReturnDataSet.Tables.Count > 0)
{
foreach (DataTable dt in dsop.ReturnDataSet.Tables)
{
if (dt.Rows.Count > 0 && dt.Columns.Count > 1)
{
foreach (DataRow dr in dt.Rows)
{ //Alarm table[0]
if (dt.TableName == "Table")
{
OperatorHistory operatorReportEntity = new peratorHistory
{
};
reportdata.Add(operatorReportEntity);
}
//ARC table[2], DW table[3], GT table[4]
else if (dt.TableName == "Table2" || dt.TableName == "Table3" || dt.TableName == "Table4")
{
OperatorHistory operatorReportEntity = new peratorHistory
{
};
reportdata.Add(operatorReportEntity);
}
}
}
}
}
--table[0]
if(LEN(@ADEventIdsForAlarms ) > 1)
select * from (
---my query logic here
) as TBL_ADEventIdsForAlarms
else
select 'TBL_ADEventIdsForAlarms'
--table[1]
--/* Just Message */ UNION ALL
if(LEN(@ADEventIdsForOPR ) > 1)
---my query logic here
) as TBL_ADEventIdsForOPR
else
select 'TBL_ADEventIdsForOPR'
--table[2]
if(LEN(@ADEventIdsForARC) > 1)
select * from (
---my query logic here
) as TBL_ADEventIdsForARC
else
select 'TBL_ADEventIdsForARC'
你可以返回一個額外的結果集來命名表,如下所示:
SELECT 'firstTableName' AS tbl
UNION
SELECT 'secondTableName' AS tbl
UNION
...
如果這是第一個結果集,您可以使用它來將后續結果集命名為 go。
可能這可能是解決方法
Create procedure psfoo ()
AS
select * ,'tbA' as TableName from tbA
select * ,'tbB' as TableName from tbB
然后在 C# 代碼
foreach (DataTable dt in ds.Tables)
{
if (dt.Rows[0]["TableName"].ToString().Contains("tbA"))
{
}
else if (dt.Rows[0]["TableName"].ToString().Contains("tbB"))
{
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.