How to retrieve second resultset from DataReader to Datatable? - c#

I have an sp that brings back two sets of results. I need to put both of these in a datatable and convert them into a datamodel.
How can I get the second set of results?
SqlConnection connection = new SqlConnection(connectionstring);
ce.Database.Initialize(force: false);
connection.Open();
SqlCommand cmd = new SqlCommand("GetJournal", connection);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
var dataTable = new DataTable();
dataTable.Load(reader);
List<Header> headerList = dataTable.AsEnumerable().Select(values =>
new Header
{
HeaderId = values.Field<Int32>("HeaderId").ToString()
}).ToList();
myList1 = headerList;
myList2 = detailList; <_---- I need to populate detail list
Also is naming all of the fields explicitly the most efficient way to load this list? Is there some sort of serialization that I can do instead? I can have tables up to 500 columns

Until the reader is not closed you can load the further tables. If you have multiple results I suggest you to populate a DataSet, which can contain multiple DataTable instances:
public static DataSet ToDataSet(IDataReader reader)
{
DataSet ds = new DataSet();
while (!reader.IsClosed)
{
DataTable dt = new DataTable();
dt.Load(reader);
ds.Tables.Add(dt);
}
return ds;
}

Related

How to convert collections to DataTable for Ado.Net SqlDataAdapter.Update?

How to finish the following function which accept three collection parameters for deleted, inserted and updated records and convert the collections to a DataTable for DataAdapter to update the table?
I found a way to convert List to DataTable at How to fill a datatable with List<T>. However, it doesn't set the insert, update and delete flags in DataTable?
void Save(
IEnumerable<int> deleted,
IEnumerable<Poco1> inserted,
IEnumerable<Poco1> updated)
{
var dt = new DataTable();
.... // Initialize dt with deleted, inserted and update?
using (var con = new SqlConnection(ConnectionStr))
{
con.Open();
var da = new SqlDataAdapter("select * from table", con);
da.Update(dt);
}
}
Or is there a better way to update the database table from these three collections? (C# 3.5)
First off, your going to want to also define the Insert, Update and Delete commands:
// Create the other commands.
da.InsertCommand = new SqlCommand("...how to insert");
da.UpdateCommand = new SqlCommand("...how to update");
da.DeleteCommand = new SqlCommand("...how to delete");
Alternatively you can try to use DbCommandBuilder to do it for you at runtime:
// Create the DbCommandBuilder.
DbCommandBuilder builder = factory.CreateCommandBuilder();
builder.DataAdapter = da;
// Get the insert, update and delete commands.
da.InsertCommand = builder.GetInsertCommand();
da.UpdateCommand = builder.GetUpdateCommand();
da.DeleteCommand = builder.GetDeleteCommand();
Next you need to define the DataTables to match the table you are targeting:
DataTable dt = new DataTable();
dt.Columns.Add(add your columns...)
Then you need to add rows to the DataTable, making sure to mark the row as inserted, updated or deleted.
DataRow dr = dt.NewRow();
dr["your column"] = ...
// Don't forget to add the row to the table!
dt.Rows.Add(dr);
// Once the row is added then go ahead and mark it as deleted, modified or new
dr.Delete()
// or
dr.SetAdded();
// or
dr.SetModified();
It wont work the way you are doing , do like this
using (var con = new SqlConnection(ConnectionStr))
{
con.Open();
var da = new SqlDataAdapter("select * from table", con);
var ds=new DataSet();
da.Fill(ds);
var dt= ds.Tables[0];
// all deleted rows
foreach(DataRow dr in dt.Rows.ToList())
{
if(deleted.ToList().Contains((int)dr["id"]))
{
dr.Delete();
}
//all updated rows
foreach(var poco in updated.ToList()
{
DataRow dr = table.Select("id="+poco.id).FirstOrDefault();
dr["field1]=poco.feild1
....set all updated values
}
//all inserted rows
foreach(var poco in inserted.ToList())
{
var dr= dt.NewRow();
dr["id"]=poco.id;
..set all fields
dt.Rows.Add(dr);
}
}
dt.Accept
da.Update(dt);
}

SQLite - storing the column names of a table in a list of strings

I don't know how to store the column names from a SQLite table into a list of strings.
The following code fills a dataGridView with the column names (amongst other things):
string sDatabasePath = DBPath();
SQLiteConnectionStringBuilder datasource = new SQLiteConnectionStringBuilder();
datasource.Add("Data Source", sDatabasePath);
datasource.Add("Version", "3");
datasource.Add("New", "False");
datasource.Add("Compress", "True");
using (SQLiteConnection connection = new SQLiteConnection(datasource.ConnectionString))
{
connection.Open(); //opens connection
SQLiteCommand getColumnNames = new SQLiteCommand("PRAGMA table_info('myTable');", connection);
SQLiteDataAdapter myAdapter = new SQLiteDataAdapter(getColumnNames);
DataSet myDataSet = new DataSet();
//myAdapter.Fill(myDataSet, "name");
this.dataGridView1.DataSource = myDataSet;
this.dataGridView1.DataMember = "name";
connection.Close();
}
If you are looking to bind your query to a list and not a DataGridView, then you should use a data reader and not a data set e.g.
using (SQLiteConnection connection = new SQLiteConnection(datasource.ConnectionString))
using (SQLiteCommand cmd = new SQLiteCommand("PRAGMA table_info('myTable');"))
{
connection.Open(); //opens connection
var tableNames = new List<string>();
using (SQLiteDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
tableNames.Add(reader.GetString(0)); // read 'name' column
}
}
return tableNames;
}
DataTable dtb = new DataTable();
myAdapter.Fill(dtb);
string[] names = new string[dtb.Rows.Count];
for (int i = 0; i < dtb.Rows.Count; i++)
{
DataRow row = dtb.Rows[i];
names[i] = row[0].ToString();
}

Modifying DataTable which is part of DataSet in C# - changes not showing in DataSet

I'm working in C# and I have a DataSet and a DataTable. I've added the DataTable to the DataSet. Then I populate the DataTable with a SQL query. In the debugger, I can see data in my DataTable. I see my DataTable in the DataSet's list of tables, but it's a null table (i.e., no columns, no data). Why is the data not showing up? Here's my code:
DataSet ds = new DataSet();
DataTable dt = new DataTable("BaseData");
ds.Tables.Add(dt);
List<SqlParameter> paramz = new List<SqlParameter>();
paramz.Add(new SqlParameter("#LitHoldDetailsID", litHoldDetailsID));
dt = LHClassLibrary.LHDataAccessLayer.ExecuteSelect("usp_GetLitHoldDetails_A", paramz);
I've tried
ds.AcceptChanges();
but that doesn't help. Do I really have to to define all the columns in the DataTable ahead of time? This is a query that returns a large number of columns, so I'm hoping I can skip that step.
You probably need to use SqlAdaptor.Fill(DataTable) like such:
string sql = #"Data Source=.;Initial Catalog=test;Integrated Security=True";
SqlConnection conn = new SqlConnection(sql);
conn.Open();
SqlDataAdapter adaptor = new SqlDataAdapter("<sql query>", conn);
DataTable dt = new DataTable();
adaptor.Fill(dt);
I will try to change the order of your code execution in this way
DataSet ds = new DataSet();
List<SqlParameter> paramz = new List<SqlParameter>();
paramz.Add(new SqlParameter("#LitHoldDetailsID", litHoldDetailsID));
DataTable dt = LHClassLibrary.LHDataAccessLayer.ExecuteSelect("usp_GetLitHoldDetails_A", paramz);
dt.TableName = "BaseData";
if(dt.DataSet != null) dt.DataSet.Tables.Remove(dt);
ds.Tables.Add(dt);
I suppose that the ExecuteSelect method will initialize and returns a DataTable with all the columns and rows returned by your stored procedure.
Only at this point the DataTable is added to your DataSet, not before.
In your code, the variable dt is assigned to a DataTable returned by ExecuteSelect but this is not the same reference to the DataTable created before and thus your DataSet remains with an empty table.
I always do it this way; hope this helps!
using (SqlConnection con = new SqlConnection(SqlConString))
{
string command = "Your Query Here...";
using (SqlCommand cmd = new SqlCommand(command, con))
{
cmd.Parameters.AddWithValue("#Param", SqlDbType.Type).Value = YourParameter;
con.Open();
using (SqlDataAdapter da = cmd.ExecuteNonQuery())
{
da.Fill(dt);
}
}
}

Stored procedure in C# datagridview instead of listbox

I have a problem with stored procedures.
This code works (with a ListBox)
private void button4_Click(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings["connString"].ConnectionString;
SqlConnection connection = new SqlConnection(connectionString);
string sqlCmd = "Drie duurste producten";
SqlCommand cmd = new SqlCommand(sqlCmd, connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = sqlCmd;
connection.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
listBox1.Items.Add(reader.GetValue(0).ToString());
}
}
connection.Close();
}
But how can I add this data to a DataGridView instead of a ListBox?
Thank you!
Change to
......
using (SqlDataAdapter adapter = new SqlDataAdapter())
{
DataTable dt = new DataTable();
adapter.SelectCommand = cmd; {
adapter.Fill(dt);
dataGridView1.DataSource = dt;
}
......
usually a DataGridView is filled binding a complete datasource to its DataSource property and letting the control to figure out how to configure its columns and the formatting of the values displayed
SqlDataAdapter is the simplest way to do it.
But it is also possible to create DataTable and populate it manually and assign DataSource value of DataGridView to DataTable instance:
...
DataTable dt = new DataTable("test");
dt.Columns.Add("test");
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
DataRow dr = dt.NewRow();
dr[0] = reader.GetValue(0).ToString();
dt.Rows.Add(dr);
}
}
dataGridView1.DataSource = dt;
....
static public long Insert(BillAO ao)
{
try
{
SqlParameter[] Params =
{
new SqlParameter("#Status",ao.Status)
, new SqlParameter("#BAID",ao.BAID)
, new SqlParameter("#PhieuKhamID",ao.PhieuKhamID)
, new SqlParameter("#ThuNganID",ao.ThuNganID)
, new SqlParameter("#Ngay",ao.Ngay)
, new SqlParameter("#SoTien",ao.SoTien)
, new SqlParameter("#LyDo",ao.LyDo)
, new SqlParameter("#GhiChu",ao.GhiChu)
, new SqlParameter("#CreatedBy",ao.CreatedBy)
, new SqlParameter("#CreatedTime",ao.CreatedTime)
, new SqlParameter("#LastModifiedBy",ao.LastModifiedBy)
, new SqlParameter("#LastModifiedTime",ao.LastModifiedTime)
};
int result = int.Parse(SqlHelper.ExecuteScalar(HYPO.Utils.Config.ConnString, CommandType.StoredProcedure, "SP_Bill_Insert", Params).ToString());
return result;
}
catch (Exception ex)
{
if (ex.Message.Contains("duplicate"))
{
return -2;
}
return -1;
}
}
You need to use SqlDataAdapter to get the result of stored procedure in data table.
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
da.Fill(dt);
dataGridView1.DataSource = dt;
you don't need a CommandReader for this, all you have to do is to use DataAdapter and DataSet. and bind the dataset into your DataGridView
DataSet ds = new DataSet();
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(ds);
dataGridView1.DataSource = ds.Tables[0];
}
You can do it with DataTable Or DataSet To Fill Data.... Here i did with DataTable....
Datatable data = new Datatable();
using (SqlDataAdapter adp = new SqlDataAdapter())
{
adp.SelectCommand = cmd;
adp.Fill(data);
GridView1.DataSorce = data;
GridView1.DataBind(); <--- Needed to bind GridView at a time While Filling DataTable data
}
You Can Also Check If DataTable Contains Data Or Not By This Way Before assigning DataTable to Gridview1.......
if(data.Rows.Counnt > 0)
{
GridView1.DataSorce = data;
GridView1.DataBind();
}
public void whateverToolStripMenuItem_Click(object sender, EventArgs e) {
// A previously declared and instantiated OpenFileDialog, i put it from Design Mode, but you can just
// declare it as
OpenFileDialog dlgImport = new OpenFileDialog();
//We show the dialog:
dlgImport.ShowDialog();
// We declare a variable to store the file path and name:
string fileName = dlgImport.FileName;
try {
// We invoke our method, wich is created in the following section, and pass it two parameters
// The file name and .... a DataGridView name that we put is the Form, so we can also see what
// We imported. Cool, isn't it?
importExcel(fileName, gridMain);
}
// It is best to always try to handle errors, you will se later why it is OleDbException and not
catch (OleDbException ex) {
MessageBox.Show("Error ocurred: " + ex.Message);
}
}

How do I store multiple results from a stored procedure into a dataset?

How do I combine to result sets from a StoredProcedure into one dataset in ASP.NET?
Below is my code in asp.net
SqlDataAdapter adap = new System.Data.SqlClient.SqlDataAdapter("sp_Home_MainBanner_TopStory",con);
adap.SelectCommand.CommandType = CommandType.StoredProcedure;
adap.SelectCommand.Parameters.AddWithValue("#rows", 9);
DataSet DS = new DataSet();
adap.Fill(DS, "Table1");
adap.Fill(DS, "Table2");
GridView1.DataSource = DS.Tables["Table2"];
GridView1.DataBind();
Even if there were two adapters, how could I combine the results into one dataset?
In MS SQL we create a procedure like:
[ create proc procedureName
as
begin
select * from student
select * from test
select * from admin
select * from result
end
]
In C#, we write following code to retrieve these values in a DataSet
{
SqlConnection sqlConn = new SqlConnection("data source=(local);initial catalog=bj001;user id=SA;password=bj");
SqlCommand sqlCmd = new SqlCommand("procedureName", sqlConn);
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlConn.Open();
SqlDataAdapter sda = new SqlDataAdapter(sqlCmd);
DataSet ds = new DataSet();
sda.Fill(ds);
sqlconn.Close();
// Retrieving total stored tables from a common DataSet.
DataTable dt1 = ds.Tables[0];
DataTable dt2 = ds.Tables[1];
DataTable dt3 = ds.Tables[2];
DataTable dt4 = ds.Tables[3];
// To display all rows of a table, we use foreach loop for each DataTable.
foreach (DataRow dr in dt1.Rows)
{
Console.WriteLine("Student Name: "+dr[sName]);
}
}
A DataSet contains Tables. For your above example, if you had two SqlDataAdapters, each calling a stored procedure and stored them like you did above.
adapter1.Fill(DS, "Table1");
adapter2.Fill(DS, "Table2");
This will take the table results from your first query and store it in the DataSet DS as Table1. It will then store another Table (Table2) in the same DataSet. To access these tables you use the following code:
DS.Tables["Table1"] //Or Table2, or whatever you name it during your Fill.
You already have the right process, you just need to look up how a DataSet works and decide how you want to call your information.
IF you want to combine your results into one DataTable however, you will need to iterate through the tables and combine information.
ex:
DataTable combinedTable = new DataTable();
//Create columns
foreach (DataRow row in DS.Tables["Table1"].Rows)
{
//Create rows? Copy information over? Whatever you want to do.
}
try using this:
adapter1.Fill(DS, "Table1, Table2");
this works here so...

Categories