I am trying to read data from a database and store it to DataSet as result. The point of this is that I want to create a Report in DevExpress which contains multiple parameter. When I store data to dataset I want to filter report based on User Input.
public void BindToData(int OrgId, bool Status)
{
try
{
string connString = #"Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=DesignSaoOsig1;Integrated Security=True";
string strproc = "TestReport";
using (SqlDataAdapter sda = new SqlDataAdapter(strproc, connString))
{
sda.SelectCommand.CommandType = CommandType.StoredProcedure;
sda.SelectCommand.Parameters.Add("#Status", SqlDbType.Bit).Value = Status;
sda.SelectCommand.Parameters.Add("#OrgJed", SqlDbType.Int).Value = OrgId;
DataSet ds = new DataSet();
sda.Fill(ds);
XtraReport report = new XtraReport();
report.DataSource = ds;
}
}
catch (Exception)
{
throw;
}
}
Button click to run function
protected void Button1_Click(object sender, EventArgs e)
{
int OrgId = 1;
bool Status = true;
BindToData(OrgId,Status);
}
So far this is code which I wrote but when I run it report.DataSource = ds doesn't get any result.
When I debug it, I didn't see where the error is.
Stored Procedure
USE [DesignSaoOsig1]
GO
/****** Object: StoredProcedure [dbo].[TestReport] Script Date: 29. 5. 2020. 09:20:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[TestReport]
(
#Status bit,
#OrgJed int
)
AS
BEGIN
SELECT TOP 1 OrgUnitID
FROM tblZaposleni_AD
--WHERE Status = #Status AND
-- OrgUnitID = #OrgJed
END
I have just run your exact code with a different connection string:
try
{
string connString = #"Confidential";
string strproc = "TestReport";
using (SqlDataAdapter sda = new SqlDataAdapter(strproc, connString))
{
sda.SelectCommand.CommandType = CommandType.StoredProcedure;
sda.SelectCommand.Parameters.Add("#Status", SqlDbType.Bit).Value = true;
sda.SelectCommand.Parameters.Add("#OrgJed", SqlDbType.Int).Value = 1;
DataSet ds = new DataSet();
sda.Fill(ds);
string temp = "123"; // Line to set breakpoint on
}
}
catch (Exception)
{
throw;
}
And it gives me a single table result with a single row as show in the watch window below:
Note in addition to selecting the id from a table I have selected the input parameters so they are visible and can be checked that what comes out is the same as what went in.
Related
I have a program that reads data from database and displays it onto spreadsheetcontrol(devexpress).
I would like your help in enabling the program to get changes to the dataset on button_click, and then save it back into the database.
Thanks
here is a snippet of the code
mentwall_DataDataSet ds = new mentwall_DataDataSet();
mentwall_DataDataSetTableAdapters.DATABASETableAdapter databaseAdapter = new mentwall_DataDataSetTableAdapters.DATABASETableAdapter();
databaseAdapter.Fill(ds.DATABASE);
dv = new DataView(ds.DATABASE);
mentwall_DataDataSet ds2 = new mentwall_DataDataSet();
mentwall_DataDataSetTableAdapters.RegsTableAdapter regsAdapter = new mentwall_DataDataSetTableAdapters.RegsTableAdapter();
regsAdapter.Fill(ds2.Regs);
dv2 = new DataView(ds2.Regs);
This binds the data source
Worksheet worksheet = workbook.Worksheets[2];
worksheet.DataBindings.BindToDataSource(dv, 1, 0);
Worksheet worksheet2 = workbook.Worksheets[3];
worksheet2.DataBindings.BindToDataSource(dv2, 1, 0);
I have done exactly the same, an application which shows content of a SQL table in a DevExpress Grid Control ( Windows Forms ) and when i click save button all changes ( including new rows added or deleted rows ) are persisted to the SQL Server database, here is a snippet of my DAL class which handles the database logic of saving:
the main point here is to use the SqlCommandBuilder class, which must be initialized with at least the select command and then all other commands are generated automatically, I have written this code > 5 years ago and i still use this app daily.
public int UpdateSQLDataTable(string connectionString, string TableName, DataTable dtSource)
{
try
{
using (SqlConnection sConn = new SqlConnection(connectionString))
{
sConn.Open();
var transaction = sConn.BeginTransaction();
try
{
var command = sConn.CreateCommand();
command.Transaction = transaction;
command.CommandText = $"SELECT TOP 1 * FROM {TableName} WITH (NOLOCK)";
command.CommandType = CommandType.Text;
// timeoput of 5 minutes
command.CommandTimeout = 300;
SqlDataAdapter sAdp = new SqlDataAdapter(command);
SqlCommandBuilder sCMDB = new SqlCommandBuilder(sAdp);
int affectedRecords = sAdp.Update(dtSource);
transaction.Commit();
return affectedRecords;
}
catch (Exception /* exp */)
{
transaction.Rollback();
throw;
}
}
}
catch (Exception exc)
{
Logger logger = new Logger();
logger.Error(string.Format("connectionString: '{0}', TableName: '{1}'", connectionString, TableName), exc);
return int.MinValue;
}
}
I have this stored procedure that gets the product table with provided parameter
CREATE PROCEDURE DisplayProductParameter #id nvarchar(100)
AS
BEGIN
SET NOCOUNT ON;
SELECT P.product_id, P.product_name, P.product_price, T.[type_name], T.[type_fee], T.[type_id]
FROM Product P
INNER JOIN [Product Type] T ON P.[type_id] = T.[type_id]
WHERE P.product_id = #id
END;
GO
I call it with this function in C#
public SqlCommand InitSqlCommand(string query, CommandType commandType)
{
var Sqlcommand = new SqlCommand(query, con);
Sqlcommand.CommandType = commandType;
return Sqlcommand;
}
Then I store it in a DataTable
public DataTable GetData(SqlCommand command)
{
var dataTable = new DataTable();
var dataSet = new DataSet();
var dataAdapter = new SqlDataAdapter { SelectCommand = command };
dataAdapter.Fill(dataTable);
return dataTable;
}
Then this is how I get the DataTable
public DataTable DisplayProductParameter()
{
string getProductIdParam = "DisplayProductParameter";
var command = Connection.InitSqlCommand(getProductIdParam, CommandType.StoredProcedure);
command.Parameters.AddWithValue("#id", P.Id);
return Connection.GetData(command);
}
This is how I should autofill textboxes whenever I click on the combobox
private void cmbProductId_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
p.Id = cmbProductId.SelectedItem.ToString();
dtbProduct = po.DisplayProductParameter();
for (int i = 0; i < dtbProduct.Rows.Count; i++)
{
txtProductType.Text = dtbProduct.Rows[i]["type_name"].ToString();
txtPrice.Text = dtbProduct.Rows[i]["product_price"].ToString();
txtProductName.Text = dtbProduct.Rows[i]["product_name"].ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
But I get this error message at the start of the form
Procedure or function 'DisplayProductParameter' expects parameter
'#id', which was not supplied.
Logically your code seems correct.
In order to get more information on where and why this is happening, could you add a breakpoint on this line:
public DataTable DisplayProductParameter()
{
string getProductIdParam = "DisplayProductParameter";
var command = Connection.InitSqlCommand(getProductIdParam, CommandType.StoredProcedure);
-->command.Parameters.AddWithValue("#id", P.Id);
return Connection.GetData(command);
}
and run in debugging mode to see what the value of P.Id is. It could be passing a null or empty string value into the procedure.
I'm new to using SqlDataAdpter and I'm trying to execute a stored procedure. The stored procedure executes successfully but no rows are returned. I've used SQL Server Profiler to monitor the call and it runs successfully (I can copy and execute the query from profiler without modifying it and get results).
I have the following:
public ActionResult Index()
{
SqlConnection conn = null;
DataSet results = null;
try
{
string connectionString = // ... my connection
conn = new SqlConnection(connectionString );
string query = #"usp_mySP";
conn.Open();
SqlDataAdapter sqlAdpt = new SqlDataAdapter(query, conn);
sqlAdpt.SelectCommand.CommandType = CommandType.StoredProcedure;
var dataDate = new SqlParameter { ParameterName = "#DataDate", Value = DateTime.Now };
var idList = new SqlParameter { ParameterName = "#IDList", Value = "1231,2324,0833" };
sqlAdpt.SelectCommand.Parameters.Add(dataDate);
sqlAdpt.SelectCommand.Parameters.Add(idList);
results = new DataSet();
sqlAdpt.Fill(results);
sqlAdpt.Dispose();
}
catch (SqlException e)
{
throw new Exception("Exception:" + e.Message);
}
finally
{
if (conn != null)
conn.Close();
}
return View(results);
}
When I inspect the DataSet through the debugger, it always returns 0 rows.
Please help with what I'm doing wrong?
Note: I've also tried (but do NOT prefer) executing as a SQL command:
EXEC usp_mySP #DataDate, #IDList
and it didn't work either as I got int to varchar conversion errors.
I think you try to add SqlParameter using SqlCommand like this :
SqlCommand cmd = new SqlCommand();
cmd.parameter.addwithvalue(#DataDate,DateTime.Now);
So the reason was because of set nocount on. I added it to my sp and it works. Thank you everyone for clarifying.
private void button1_Click(object sender, EventArgs e)
{
try
{
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "Data Source=*******;Initial Catalog=ChatApp;User ID=Chatapplication;Password=****";
conn.Open();
SqlCommand cmd = new SqlCommand();
string chatroomidno = textBox1.Text;
string chatroomname = textBox2.Text;
//cmd.CommandText = "Select ChatRoomID=#ChatRoomID,ChatRoomName=#ChatRoomName from tblChatRoom";
//cmd.Connection = conn;
SqlDataAdapter adapt = new SqlDataAdapter("Chatroomapp",conn);
adapt.SelectCommand.CommandType = CommandType.StoredProcedure;
DataSet ds=new DataSet();
DataTable dt = new DataTable();
adapt.SelectCommand.Parameters.Add(new SqlParameter("#ChatRoomID", SqlDbType.VarChar, 100));
adapt.SelectCommand.Parameters["#ChatRoomID"].Value = chatroomidno;
adapt.SelectCommand.Parameters.Add(new SqlParameter("#ChatRoomName", SqlDbType.VarChar, 50));
adapt.SelectCommand.Parameters["#ChatRoomName"].Value = chatroomname;
adapt.Fill(ds, "tblChatRoom");
if (dt.Rows.Count > 0)
{
MessageBox.Show("Connection Succedded");
}
else
{
MessageBox.Show("Connection Fails");
}
}
catch (Exception ex)
{
MessageBox.Show("Error", ex.Message);
}
}
While compiling the program I got only connection fails message box, in the database. I found correct, how to overcome the program to get the connection succeeded message box.
Well, you're filling the ds data set - but then you're checking the dt data table for presence of rows... that's never going to work, of course!
If you only need a single DataTable - just use and fill that data table alone - no need for the overhead of a DataSet. Also, put your SqlConnection and SqlCommand into using blocks like this:
using (SqlConnection conn = new SqlConnection("Data Source=*******;Initial Catalog=ChatApp;User ID=Chatapplication;Password=****"))
using (SqlCommand cmd = new SqlCommand("Chatroomapp", conn))
{
string chatroomidno = textBox1.Text;
string chatroomname = textBox2.Text;
SqlDataAdapter adapt = new SqlDataAdapter(cmd);
adapt.SelectCommand.CommandType = CommandType.StoredProcedure;
adapt.SelectCommand.Parameters.Add(new SqlParameter("#ChatRoomID", SqlDbType.VarChar, 100));
adapt.SelectCommand.Parameters["#ChatRoomID"].Value = chatroomidno;
adapt.SelectCommand.Parameters.Add(new SqlParameter("#ChatRoomName", SqlDbType.VarChar, 50));
adapt.SelectCommand.Parameters["#ChatRoomName"].Value = chatroomname;
// fill the data table - no need to explicitly call `conn.Open()` -
// the SqlDataAdapter automatically does this (and closes the connection, too)
DataTable dt = new DataTable();
adapt.Fill(dt);
if (dt.Rows.Count > 0)
{
MessageBox.Show("Connection Succedded");
}
else
{
MessageBox.Show("Connection Fails");
}
}
And just because you get back no rows in dt.Rows doesn't necessarily mean that your connection failed..... it could just be that there are no rows that match your search critieria! The connection worked just fine - but the SQL command just didn't return any rows.
Connection failed means that something went wrong between your program and the database. No records returned does not mean that the connection failed. It just means that your table is empty - it contains no records.
Using ADO.NET and a stored procedures would have been a little different from what you have done it. If you need to check if the connection failed, maybe it is better to check the type of exception that is returned in the catch part.
Below is how I would have done it. I would have created a separate method that would have handled my call, and then in your button1_Click I would have just called this method:
public async Task<ChatRoom> GetAsync(string chatRoomId, string chatRoomName)
{
try
{
string connectionString = ConfigurationManager.ConnectionStrings["Db"].ConnectionString;
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
{
await sqlConnection.OpenAsync();
using (SqlCommand sqlCommand = new SqlCommand("ChatRooms_Get", sqlConnection))
{
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.Parameters.Add(new SqlParameter("#ChatRoomID", chatRoomId));
sqlCommand.Parameters.Add(new SqlParameter("#ChatRoomName", chatRoomName));
using (SqlDataReader sqlDataReader = await sqlCommand.ExecuteReaderAsync())
{
ChatRoom chatRoom = null;
if (await sqlDataReader.ReadAsync())
{
chatRoom = new ChatRoom();
chatRoom.Id = sqlDataReader.GetFieldValue<string>(0);
chatRoom.Name = sqlDataReader.GetFieldValue<string>(1);
chatRooms.Add(chatRoom);
}
return chatRoom;
}
}
}
}
catch (Exception exception)
{
// Try checking if the connection failed here
throw exception;
}
}
My chat room domain model could have looked like this:
public class ChatRoom
{
public string Id { get; set; }
public string Name { get; set; }
}
And the stored procedure would have looked like this:
CREATE PROCEDURE [dbo].[ChatRooms_Get]
(
#ChatRoomID VARCHAR(100),
#ChatRoomName VARCHAR(50)
)
AS
BEGIN
SET NOCOUNT ON;
SELECT
ChatRoomID,
ChatRoomName
FROM
tblChatRoom
WHERE
ChatRoomID = #ChatRoomID
AND ChatRoomName = #ChatRoomName;
END
GO
And then in the calling method you would get the chatroom and do with it whatever you need to do with it. For this example I just checked if it exists or not:
try
{
ChatRoom chatRoom = await chatRoomRepository.GetAsync(chatRoomId, chatRoomName);
if (chatRoom != null)
{
MessageBox.Show("Record found");
}
else
{
MessageBox.Show("No record found");
}
}
catch (Exception exception)
{
throw exception;
}
I hope this can help.
I am not getting filled dataset after executing a stored procedure.
protected void btnsub_Click(object sender, EventArgs e)
{
ArrayList arInsert = ReturnParameter_insert();
DataSet dsInsertProfile = objadmin.GetGridData(arInsert, objconstant.sSP_INSERT_PROFILE);
if(int.Parse(dsInsertProfile.Tables[0].Rows[0].ItemArray[0].ToString())== 0)
{
lblThank.Text = "Your profile have been successfully saved.";
}
else
{
lblThank.Text = "Your profile is not saved, please try again later.";
}
}
public ArrayList ReturnParameter_insert()
{
ArrayList arProfile = new ArrayList();
Object[] c_first_name = new object[3] { "#strFname", "Varchar", (txtfname.Text != "") ? txtfname.Text : "" };
arProfile.Add(c_first_name);
return arProfile;
}
public DataSet GetGridData(ArrayList dbArray, string sSpName)
{
DataSet dsDataSet = new DataSet();
dsDataSet = datamanager.GetGridData(dbArray, sSpName);
return dsDataSet;
}
public static SqlDbType GetSqlDataType(string sDataType)
{
return (sDataType == "Integer") ? SqlDbType.Int : (sDataType == "Varchar") ? SqlDbType.VarChar : (sDataType == "Date") ? SqlDbType.Date : SqlDbType.BigInt;
}
public static DataSet GetGridData(ArrayList dbArray, string sSpName)
{
DataSet dsDataSet = new DataSet();
SqlConnection cn = createConnection();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = sSpName;
object objPrMtrName;
object objSqlType;
object objPrMtrVal;
int i;
for (i = 0; i < dbArray.Count; i++)
{
objPrMtrName = ((object[])(dbArray[i]))[0];
objSqlType = ((object[])(dbArray[i]))[1];
objPrMtrVal = ((object[])(dbArray[i]))[2];
cmd.Parameters.Add(objPrMtrName.ToString(), GetSqlDataType(objSqlType.ToString())).Value = objPrMtrVal;
}
cmd.Connection = cn;
try
{
SqlDataAdapter adp = new SqlDataAdapter(cmd);
adp.Fill(dsDataSet);
return dsDataSet;
}
catch (Exception ex)
{
throw ex;
}
finally
{
cn.Close();
cn.Dispose();
}
}
My stored procedure:
CREATE Procedure spInsert_profile
(#strFname varchar(200))
AS
BEGIN
INSERT INTO gdt_Users([c_first_name], [d_modified_dttm], [d_created_dttm])
VALUES(#strFname, GETDATE(), GETDATE())
END
Here I am using 3 tier, the same methods are working successfully for other pages but not for this particular code. The dataset in GETGRIDDATA method is filling null value. I am not able to find. Please help me....
you performing insert operation in your procedure than how is going to return to data Insert into statement does insert operation not retrieve operation.
...To retrieve data you need to call procedure with select * statement.
There is no select statement in your stored proc. adapter.fill() should recieve some sort of table from the stored proc's output.
From what I can see here you are executing a stored procedure that only performs an INSERT command, The reason you are getting a NULL value back is because a non query command such as UPDATE or INSERT will generally return only the number of rows affected e.g. 1 and not the data of the table you inserted to.
You would need to perform a SELECT command after the insert to get any data back.
The problem is in your stored procedure... you have to add select statement to the stored procedure for your return result in DataSet
Because you use Insert Into in your stored procedure.
Access based on Tables property:
SqlDataAdapter adp = new SqlDataAdapter(cmd);
adp.Fill(dsDataSet);
var table1 = dsDataSet.Tables[0];
var table2 = dsDataSet.Tables[1];
Link : http://msdn.microsoft.com/fr-fr/library/system.data.dataset.tables.aspx