I need to modify the following code so that the number of rows are limited.
// create the connection
OracleConnection conn = new OracleConnection("Data Source=oracledb;
User Id=UserID;Password=Password;");
// create the command for the stored procedure
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT_JOB_HISTORY.GetJobHistoryByEmployeeId";
cmd.CommandType = CommandType.StoredProcedure;
// add the parameters for the stored procedure including the REF CURSOR
// to retrieve the result set
cmd.Parameters.Add("p_employee_id", OracleType.Number).Value = 101;
cmd.Parameters.Add("cur_JobHistory", OracleType.Cursor).Direction =
ParameterDirection.Output;
// createt the DataAdapter from the command and use it to fill the
// DataSet
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);//Here is where I need to limit the rows
I know there is fill method which takes a maximum count.
public int Fill(
DataSet dataSet,
int startRecord,
int maxRecords,
string srcTable
)
However, I don't know what should be passed to srcTable. My stored proc has one REF_CURSOR
(OUT TYPES.REF_CURSOR).
Any help is much appreciated.
The srcTable parameter is the name of the DataTable in DataSet object.
EDIT:
The DataSet object automatically adds a table when you call Fill if you have not explicitly created one. The Default name is "Table". I do not believe the DataSet object cares about what type of data it is being filled with. It still creates the DataTable.
Before you call Fill() on your DataAdapter. Add an empty table to the DataSet with a name so you are able to access it during the Fill() method:
ds.Tables.Add("myTableName");
Then call the proper overloaded Fill() method like so:
da.Fill(ds, 1, 1000, "myTableName");
Or if you just use the default name of the table, or are unsure of the name of the table you created (doubtful):
da.Fill(ds, 1, 1000, ds.Tables[0].TableName);
Spcifically using your example it should look like this:
OracleDataAdapter da = new OracleDataAdapter(cmd);
DataSet ds = new DataSet();
ds.Tables.Add();
da.Fill(ds, 1, maxRowCount, ds.Tables[0].TableName);//Here is where I need to limit the rows
Related
I am retrieving particular column value using DataSet.
This is my code:
public DataSet GetRedirectURL(string emailId)
{
DataSet ds = new DataSet();
using (SqlConnection con = new SqlConnection(#"Connection_String_Here"))
{
con.Open();
SqlCommand sqlComm = new SqlCommand("usp_Login", con)
{
CommandType = CommandType.StoredProcedure
};
sqlComm.Parameters.AddWithValue("#EmailId", emailId);
SqlDataAdapter da = new SqlDataAdapter
{
SelectCommand = sqlComm
};
da.Fill(ds);
}
return ds;
}
I have also used DataTable instead of it but the same result.
I have checked my Stored Procedure and when I pass Parameter it shows Data. So, nothing wrong with the SP. But the Table doesn't show any data and is always empty as shown below:
What am I missing? Any help would be appreciated.
I'd suggest you to first evaluate the content of your DataSet. For instance, type in your Immediate Window (or add a quick watch) to check ds.Tables[0].Rows.Count. Basically, to assert your DataSet has been properly filled with the contents fetched from the database, and focus on the data assignment from the DataSet to the grid object you're using to display it.
Also, the .Fill() method has a returning object which is an int representing the amount of rows that have been successfully filled into the target object. For instance:
int result = da.Fill(ds);
Check the value of result after the .Fill() method has been executed.
Finally, I guess you're using a DataGridView object to visualize the results. If so, how are you binding data? Should be something like:
dataGridView1.DataSource = ds.Tables[0];
PS: As I've read in other comments, no, you don't need to execute the .Open() method on the connection. That's not necesarry, it's done implicitely when using the (using SqlConnection conn = SqlConnection..)
Through designer I have created a typed data set and included stored procedures for insert / update / delete. The problem is now, how to call those stored procedures? How to actually change data in database this way? And how to receive answer from db (number of rows changed)?
try this for get data from database.
DataSet ds = new DataSet("dstblName");
using(SqlConnection conn = new SqlConnection("ConnectionString"))
{
SqlCommand sqlComm = new SqlCommand("spselect", conn);
sqlComm.Parameters.AddWithValue("#parameter1", parameter1value);
sqlComm.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = sqlComm;
da.Fill(ds);
}
Similarly you need to call "spdelte" etc.
I found out that far easiest way is through designer - create table adapter and simply set it to call stored procedure. No extra typing needed, arguments are also added to procedure call.
I read SQL Command Builder class from
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommandbuilder.aspx and I found that I can show update done on dataset/database using select and update command.
SQL Command Builder concept is clear if I am using single dataset but what if I want to use two different dataset?
Scenario: I am reading values from database into one dataset ds1; which is assign to sql adapter and sql command builder. Now, I am reading only selected values from ds1 and storing into second dataset ds2; which is not assign to sql data adapter and sql command builder.
I am concern if I am updating any data on ds2 whether it will update database or not. Also, how should I do it using SQL Command builder and SQL Adapter.
//primary dataset
ds = new ProductDataSet();
command = new SqlCommand(
"SELECT no, name, price, cost, dept FROM PRODUCTS", connection);
adapter = new SqlDataAdapter();
adapter.SelectCommand = command;
adapter.Fill(ds, "table");
Primary dataset is fill on form load event. User will enter item no of his choice which will be search from primary ds and saved/display onto 2nd ds (2nd ds is not connected with with any adapter or command builder right now). For eg; 2nd ds have 3 items.
Now say user update any information on 2nd ds it should automatically update database and display on grid.
//2nd ds2 update code
for (int i = 0; i < ds2.Tables[0].Rows.Count; i++)
{
string item = ds2.Tables[0].Rows[i][0].ToString();
command = new SqlCommand("UPDATE PRODUCTS SET " + _colName + " = '" + _newValue + "'" + "WHERE ITEM_NO = '" + item + "'", Class1.conn);
datagrid.DataSource = ds2.Tables[0];
}
According to your suggestion if I am adding/declaring adapter/builder in above code it doesn't work. I am getting Table Mapping error.
Use another SQLAdapter and SQLCommandBuilder. The example on that page shows how to update your database. You just need to supply the fields to be updated in the form of a query, such as:
SELECT Name, Address, Phone, Email FROM Contact
and the command builder will generate the proper SQL UPDATE statement.
SqlCommandBuilder automatically generates INSERT, UPDATE and DELETE sql statements based on the SELECT statement for a single table.
For the Transact-SQL statements to be generated using SqlCommandBuilder, there are 2 steps
Step 1. Set the "SelectCommand" property of the SqlDataAdapter object
SqlDataAdapter dataAdapter = new SqlDataAdapter();
dataAdapter.SelectCommand = new SqlCommand("SELECT_Query", con);
DataSet dataSet = new DataSet();
dataAdapter.Fill(dataSet, "Students");
Step 2. Create an instance of SqlCommandBuilder class and associate the
SqlDataAdapter object created above using DataAdapter property of the SqlCommandBuilder object
SqlCommandBuilder builder = new SqlCommandBuilder();
builder.DataAdapter = dataAdapter;
Step 3. Updating records of ds1
dataAdapter.Update(ds1, "Students");
Like you Know the easier way to fill a dataset is with a dataAdapter like this :
DataSetEmp myDataSet = new DataSetEmp();
...(here Id did a select request..)
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = myCommand1;
adapter.Fill(myDataSet.myDataTable1);
AND
......(here Id did a select request..)
SqlDataAdapter adapter2 = new SqlDataAdapter();
adapter2.SelectCommand = myCommand2;
adapter2.Fill(myDataSet.myDataTable2);
//I have a Crystal report
CrystalReport1 report1 = new CrystalReport1();
report1.setDataSource(myDataSet);
This Way works perfectly good, but I want to fill data with DataReader not DataAdapter because I want to Check some values In a while(myReader.read()){ ....} loops.
You have to populate the DataTable manually using its methods and properties. Eg. creating each contained DataTable in turn (in essence re-creating the implementation of DataAdapter.Fill).
Alternately you could use the DataAdapter and before passing it to Crystal Reports use those same members to modify the DataTable's content.
For example if I run the following query:
select * from table1
select * from table2
And run it with a DB adapter (C#) I get a dataset with two tables.
How can I define the names for the result tables in SQL?
I can only do this inside the SQL. I don't have access to the c# code.
#Timothy Khouri: It can be done! EDIT: but not at the SQL level!
You can use TableMappings on the DataAdapter.
If the SelectCommand of a DataAdapter returns multiple result sets, the DataAdapter uses table mappings to fill corresponding DataTables in a DataSet. By default, the first result set will be filled to a DataTable named "Table", and the second result set will be filled to a DataTable named "Table1" etc.
SqlDataAdapter sqlDa = new SqlDataAdapter();
SqlCommand selectCmd = new SqlCommand();
selectCmd.CommandText = "spReturnMultpileResultSets";
selectCmd.CommandType = CommandType.StoredProcedure;
selectCmd.Connection = this.sqlConnection1;
sqlDa.SelectCommand = selectCmd;
// Add table mappings to the SqlDataAdapter
sqlDa.TableMappings.Add("Table", "Customers");
sqlDa.TableMappings.Add("Table1", "Orders");
// DataSet1 is a strongly typed DataSet
DataSet1 ds = new DataSet1();
this.sqlConnection1.Open();
sqlDa.Fill(ds);
this.sqlConnection1.Close();
Refs:
http://blogs.msdn.com/vsdata/archive/2007/03/08/tableadapter-multiple-result-sets.aspx
http://www.eggheadcafe.com/software/aspnet/32696845/strongly-typed-datasets.aspx