Updating a Data Source with a Dataset - sql

I need advice. I have asp.net web service and winforms client app.
Client call this web method and get dataset.
1. [WebMethod]
2. public DataSet GetSecureDataSet(string id)
3. {
4.
5.
6. SqlConnection conn = null;
7. SqlDataAdapter da = null;
8. DataSet ds;
9. try
10. {
11.
12. string sql = "SELECT * FROM Tab1";
13.
14. string connStr = WebConfigurationManager.ConnectionStrings["Employees"].ConnectionString;
15.
16. conn = new SqlConnection(connStr);
17. conn.Open();
18.
19. da = new SqlDataAdapter(sql, conn);
20.
21. ds = new DataSet();
22. da.Fill(ds, "Tab1");
23.
24. return ds;
25. }
26. catch (Exception ex)
27. {
28. throw ex;
29. }
30. finally
31. {
32. if (conn != null)
33. conn.Close();
34. if (da != null)
35. da.Dispose();
36. }
37. }
After he finish work he call this update web method. He can add, delete and edit rows in table in dataset.
[WebMethod]
public bool SecureUpdateDataSet(DataSet ds)
{
SqlConnection conn = null;
SqlDataAdapter da = null;
SqlCommand cmd = null;
try
{
DataTable delRows = ds.Tables[0].GetChanges(DataRowState.Deleted);
DataTable addRows = ds.Tables[0].GetChanges(DataRowState.Added);
DataTable editRows = ds.Tables[0].GetChanges(DataRowState.Modified);
string sql = "UPDATE * FROM Tab1";
string connStr = WebConfigurationManager.ConnectionStrings["Employees"].ConnectionString;
conn = new SqlConnection(connStr);
conn.Open();
cmd = new SqlCommand(sql, conn);
da = new SqlDataAdapter(sql, conn);
if (addRows != null)
{
da.Update(addRows);
}
if (delRows != null)
{
da.Update(delRows);
}
if (editRows != null)
{
da.Update(editRows);
}
return true;
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (conn != null)
conn.Close();
if (da != null)
da.Dispose();
}
}
Code on client side
1. //on client side is dataset bind to datagridview
2. Dataset ds = proxy.GetSecureDataSet("");
3. ds.AcceptChanges();
4.
5. //edit dataset
6.
7.
8. //get changes
9. DataSet editDataset = ds.GetChanges();
10.
11. //call update webmethod
12. proxy.SecureUpdateDataSet(editDataSet)
But it finish with this error :
System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.InvalidOperationException: Update requires a valid UpdateCommand when passed DataRow collection with modified rows.
at WebService.Service.SecureUpdateDataSet(DataSet ds) in D:\Diploma.Work\WebService\Service1.asmx.cs:line 489
Problem is with SQL Commad, client can add, delete and insert row, how can write a corect SQL command.... any advice please? Thank you

try this:
[WebMethod]
public bool SecureUpdateDataSet(DataSet delta)
{
string connStr = WebConfigurationManager.ConnectionStrings["Employees"].ConnectionString;
using(var conn = new SqlConnection(connStr))
{
conn.Open();
string sql = "select * from tab1 where 1 = 0";
using(var da = new SqlDataAdapter(sql, conn))
{
var builder = new SqlCommandBuilder(ad);
da.InsertCommand = builder.GetInsertCommand();
da.UpdateCommand = builder.GetUpdateCommand();
da.DeleteCommand = builder.GetDeleteCommand();
da.Update(delta);
return true;
}
}
return false;
}

I think SqlCommandBuilder is the better and convenient way for adding, updating and deleting data in the database through dataset.

Related

Can't use retrieved data from one query into another one?

I need to use a variable (edifcodigo) which assigned value is retrieved from one query to insert it in a table by using other query but there is a error that says this variable is not available in actual context. I'm kind of new in aspnet, could anybody know how to figure this out?
This is the code I have:
//Connect to db
string connetionString = #"myconexionstring";
string sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto= '"+ uedif +"'";
//find building code by querying the database
try
{
using (SqlConnection conexion = new SqlConnection(connetionString))
{
conexion.Open();
using (SqlCommand query = new SqlCommand(sql, conexion))
{
SqlDataReader result = query.ExecuteReader();
while (result.Read())
{
string edifcodigo = result["codigo"].ToString();
}
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
//Save referer friend
try
{
using (SqlConnection conn = new SqlConnection(connetionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("DNN_SVI_SCO_DATOS_RECOMIENDA_AMIGO_SP", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#DRA_PROYECTO_CLIENTE", System.Data.SqlDbType.VarChar).Value = edifcodigo; ;
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
That's because you declared the variable inside a different code block. Every time you open a curly bracket, you open a new code block. Every time you close the curly bracket, you close the current code block. Each code block have it's own scope - it can access variables declared in the surrounding code block, but not variables declared in "sibling" code blocks.
Also, please read about parameterized queries and how they protect you from SQL injection, and change your queries accordingly.
Also, you don't need to close the connection between the two commands, and you can reuse a single command instance in this case. Here is an improved version of your code:
//Connect to db
var connetionString = #"myconexionstring";
var sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto = #nombre_proyecto";
//find building code by querying the database
try
{
using (var conexion = new SqlConnection(connetionString))
{
conexion.Open();
using (var cmd = new SqlCommand(sql, conexion))
{
cmd.Parameters.Add("#nombre_proyecto", SqlDbType.NVarChar).Value = uedif;
var edifcodigo = cmd.ExecuteScalar();
//Save referer friend
cmd.Parameters.Clear();
cmd.CommandText = "DNN_SVI_SCO_DATOS_RECOMIENDA_AMIGO_SP";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#DRA_PROYECTO_CLIENTE", System.Data.SqlDbType.VarChar).Value = edifcodigo; ;
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
You are declaring the string variable inside your while loop, it loses scope once you exit the while loop, move it's declaration above with:
string connetionString = #"myconexionstring";
string sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto= '"+ uedif +"'";
string edifcodigo = "";
You are trying to use a variable that declared in another scope. edifcodigo should be declared in the parent scope of both try blocks.
//Connect to db
string connetionString = #"myconexionstring";
string sql = "SELECT TOP 1 id_proyecto AS codigo FROM DNN_SCO_PROY_CO_PROYECTO_TBL WHERE nombre_proyecto= '"+ uedif +"'";
string edifcodigo=""; // YOU SHOULD DECLARE edifcodigo HERE
and than rest of code will come
//find building code by querying the database
try
{
using (SqlConnection conexion = new SqlConnection(connetionString))
{
conexion.Open();
using (SqlCommand query = new SqlCommand(sql, conexion))
{
SqlDataReader result = query.ExecuteReader();
while (result.Read())
{
edifcodigo = result["codigo"].ToString();
}
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
//Save referrer friend
try
{
using (SqlConnection conn = new SqlConnection(connetionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("DNN_SVI_SCO_DATOS_RECOMIENDA_AMIGO_SP", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add("#DRA_PROYECTO_CLIENTE", System.Data.SqlDbType.VarChar).Value = edifcodigo; ;
}
}
}
catch (Exception ex)
{
Response.Write(ex.Message);
}

ASP.NET 5 - DataSet, DataTable and friends

I'm creating a new webservice in ASP.NET 5 using the new .NET Core library, so far I've only hit an issue with using DataSet and DataTable.
According to this site they are not included at this moment in time, which is fine, but I don't know what alternatives I have at this time, so I'm just looking for some guidance.
I have the following code:
public string Get(string p_sUserId, string p_sUserPassword, int p_iCustId)
{
Select qrySelect = new Select();
using (SqlConnection conn = new SqlConnection(Startup.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand(qrySelect.getData(), conn))
{
cmd.Parameters.AddWithValue("#Id", sTestId);
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
using (DataSet ds = new DataSet())
{
// foo
// bar
}
}
}
}
return "value";
}
How should I handle the data that is being return from the query? I need to build and return a string using the above data fetched from the query. Any help and guidance would be appreciated.
I believe SqlDataReader should work.
string sql = "SELECT * FROM Table";
using (SqlConnection con = new SqlConnection(Startup.ConnectionString)) {
con.Open();
using (SqlCommand command = new SqlCommand(sql, con)) {
using (IDataReader dr = command.ExecuteReader()) {
while (dr.Read()) {
//process data
}
}
}
}
DataTable and SqlDBAdapter are now supported using .NET Standard 2.0. Upgrade to VS2017 Preview, add System.Data.Common and System.Data.SqlClient nugets, and the code below should work. More detail at the blog post here -> https://blogs.msdn.microsoft.com/devfish/2017/05/15/exploring-datatable-and-sqldbadapter-in-asp-net-core-2-0/ . GitHub repo here -> https://github.com/jhealy/aspdotnetcore/tree/master/SqlClientPlay20 .
public static DataTable ExecuteDataTableSqlDA(SqlConnection conn, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)
{
System.Data.DataTable dt = new DataTable();
System.Data.SqlClient.SqlDataAdapter da = new SqlDataAdapter(cmdText, conn);
da.Fill(dt);
return dt;
}

Retrieve SQL Statement Does Not Go Into While Loop

I am having problem when doing retrieve function in 3-tier in C#. Here is the codes:
public DistributionStandardPackingUnits getSPUDetail(string distributionID)
{
DistributionStandardPackingUnits SPUFound = new DistributionStandardPackingUnits();
using (var connection = new SqlConnection(FoodBankDB.connectionString))
{
SqlCommand command = new SqlCommand("SELECT name, description, quantity FROM dbo.DistributionStandardPackingUnits WHERE distribution = '" + distributionID + "'", connection);
connection.Open();
using (var dr = command.ExecuteReader())
{
while (dr.Read())
{
string name = dr["name"].ToString();
string description = dr["description"].ToString();
string quantity = dr["quantity"].ToString();
SPUFound = new DistributionStandardPackingUnits(name, description, quantity);
}
}
}
return SPUFound;
}
When I run in browser, it just won't show up any retrieved data. When I run in debugging mode, I realized that when it hits the while loop, instead of executing the dr.Read(), it simply just skip the entire while loop and return null values. I wonder what problem has caused this. I tested my query using the test query, it returns me something that I wanted so I think the problem does not lies at the Sql statement.
Thanks in advance.
Edited Portion
public static SqlDataReader executeReader(string query)
{
SqlDataReader result = null;
System.Diagnostics.Debug.WriteLine("FoodBankDB executeReader: " + query);
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand(query, connection);
connection.Open();
result = command.ExecuteReader();
connection.Close();
return result;
}

Return nested complex types from WCF WebGet

I've created a wcf data service to return a List of complex type patient. I used the model browser to create a complex type for "Patient" and a complex type for "Contact". I'd like to add a "Contacts" property to "Patient", which would be a List.
How do I add a nested complex type list as a property and return it?
[WebGet]
public List<Patient> GetPatientByID(int tolid)
{
List<Patient> list = new List<Patient>();
// create pds user session record
SqlConnection conn = new SqlConnection("Data Source=server;Initial Catalog=db;User ID=<ID>;Password=<pwd>");
SqlCommand cmd = new SqlCommand();
try
{
// open the connection
conn.Open();
// configure the command
cmd.Connection = conn;
cmd.CommandText = "sp_tol_patient_select";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("tolid", tolid));
// execute the command and convert the decimal value
// returned by ExecuteScalar to an int to get new identity value
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
Patient itm = new Patient();
itm.MRN = reader["UNITNUMBER"].ToString();
itm.AccountNum = reader["ACCTNUM"].ToString();
itm.FullName = reader["PATNAME"].ToString();
itm.BirthDate = reader["BIRTHDATE"].ToString();
itm.Gender = reader["SEX"].ToString();
list.Add(itm);
}
return list;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
cmd.Dispose();
conn.Close();
}
}

Foxpro: Check whether table exists via vfpoledb

I access data in .dbf files via System.Data.OleDb (vfpoledb.dll). How can I find out whether table exists via SQL command? Something similar to the following on SQL server:
IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'TheTable'))
BEGIN
--Do Stuff
END
If you have a dbc file you can query it to see if the table exists.
string dbc = "northwind.dbc";
using (OleDbConnection conn = new OleDbConnection(connectionString)) {
DataTable dt = new DataTable();
string sql = string.Format(#"SELECT * FROM {0} WHERE ALLTRIM(ObjectType) = 'Table' AND UPPER(ALLTRIM(ObjectName)) = '{1}'", dbc, tableName.ToUpper());
OleDbDataAdapter da = new OleDbDataAdapter(sql, conn);
da.Fill(dt);
bool tableExists = dt != null && dt.Rows.Count == 1;
}
But really you don't need a sql command or a dbc file to get that information. You can get it straight from the OleDbConnection using the GetSchema method.
using (OleDbConnection conn = new OleDbConnection(connectionString)) {
conn.Open();
DataTable tables = conn.GetSchema("Tables");
conn.Close();
var tableExists = (from row in tables.AsEnumerable()
where row.Field<string>("Table_Name").Equals(tableName, StringComparison.CurrentCultureIgnoreCase)
select row.Field<string>("Table_Name")).FirstOrDefault() != null;
}
Additionally, if you are connecting to DBF tables that are "FREE" tables and NOT actually part of a connected "database" (.dbc), then you can just check for the file's existence or not... Such as in C# via
if( File.Exists( PathToTheDatabaseDirectory + TableYouExpect + ".DBF" ))
file is there
else
file is missing
I don't know how to do it only using SQL but maybe you could check for the existence of the file on disk using the File.Exists Method or you could write some code to check for the existence of the dbf using the OleDb classes:
private bool DbfExists(string dbfName, string connectionString)
{
bool dbfExists = true;
using(OleDbConnection conn = new OleDbConnection(connectionString))
{
string sql = string.Format("SELECT * FROM {0}", dbfName);
using(OleDbCommand command = new OleDbCommand(sql, conn))
{
OleDbDataReader reader = null;
try
{
conn.Open();
reader = command.ExecuteReader();
}
catch(Exception ex)
{
dbfExists = false;
}
finally
{
conn.Close();
reader = null;
}
}
}
return dbfExists;
}
I have not tried compiling this code so it may need to be tweaked a bit.