I have two dataset questions.
If I change any cell in a dataset, how I can update this change in a database without using an SQL update query?
How can I see dataset contents in debug mode (to see the data)?
You can't update a database without an UPDATE query. That's how updates happen. You can use libraries that abstract this away so that you don't have to see the query in your code, but the query still has to happen.
You can see the contents of a dataset in debug mode by adding it to your watch list and clicking the little magnifying glass icon. It opens up a window that lets you look at the tables in the dataset.
You can use LINQ to update data into the database, without using T-SQL Update query.
What you're looking for is a DataAdapter. It will manage updating, deleting and inserting changes.
Check this code and adapt to your needs
///<summary>Update Batch records in DataTable</summary>
///<remarks></remarks>
public void UpdateTables(System.Data.DataTable DataTable)
{
if (DataTable.TableName.Length == 0)
{
throw new Exception("The DataTable tablename is nedded.");
}
if (this.State == ConnectionState.Closed)
{
this.Connect();
}
try
{
string strTablename = DataTable.TableName, strSQL;
System.Data.IDbDataAdapter dt = null;
if (DataTable.TableName.Length == 0)
{
throw new Exception("Tablename can't be null.");
}
strSQL = "SELECT * FROM " + strTablename;
if (m_DatabaseType == DatabaseTypeEnum.Access)
{
dt = new System.Data.OleDb.OleDbDataAdapter(strSQL, m_ConnectionString);
System.Data.OleDb.OleDbCommandBuilder cb_a
= new System.Data.OleDb.OleDbCommandBuilder((System.Data.OleDb.OleDbDataAdapter)dt);
dt.InsertCommand = cb_a.GetInsertCommand();
dt.UpdateCommand = cb_a.GetUpdateCommand();
dt.DeleteCommand = cb_a.GetDeleteCommand();
((System.Data.OleDb.OleDbDataAdapter)dt).Update(DataTable);
}
else if (m_DatabaseType == DatabaseTypeEnum.SQLServer)
{
dt = new System.Data.SqlClient.SqlDataAdapter(strSQL, m_ConnectionString);
System.Data.SqlClient.SqlCommandBuilder cb_s
= new System.Data.SqlClient.SqlCommandBuilder((System.Data.SqlClient.SqlDataAdapter)dt);
dt.InsertCommand = cb_s.GetInsertCommand();
dt.UpdateCommand = cb_s.GetUpdateCommand();
dt.DeleteCommand = cb_s.GetDeleteCommand();
((System.Data.SqlClient.SqlDataAdapter)dt).Update(DataTable);
}
else if (m_DatabaseType == DatabaseTypeEnum.Oracle)
{
dt = new System.Data.OracleClient.OracleDataAdapter(strSQL, m_ConnectionString);
System.Data.OracleClient.OracleCommandBuilder cb_o
= new System.Data.OracleClient.OracleCommandBuilder((System.Data.OracleClient.OracleDataAdapter)dt);
dt.InsertCommand = cb_o.GetInsertCommand();
dt.UpdateCommand = cb_o.GetUpdateCommand();
dt.DeleteCommand = cb_o.GetDeleteCommand();
((System.Data.OracleClient.OracleDataAdapter)dt).Update(DataTable);
}
else if (m_DatabaseType == DatabaseTypeEnum.Odbc)
{
dt = new System.Data.Odbc.OdbcDataAdapter(strSQL, m_ConnectionString);
System.Data.Odbc.OdbcCommandBuilder cb_c
= new System.Data.Odbc.OdbcCommandBuilder((System.Data.Odbc.OdbcDataAdapter)dt);
dt.InsertCommand = cb_c.GetInsertCommand();
dt.UpdateCommand = cb_c.GetUpdateCommand();
dt.DeleteCommand = cb_c.GetDeleteCommand();
((System.Data.Odbc.OdbcDataAdapter)dt).Update(DataTable);
}
else
{
throw new NotImplementedException();
}
DataTable.AcceptChanges();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
Related
I have a c# web application which reads an excel file converts it to XML executes a stored procedure and returns a dataset in a specific format needed to execute a secondary update. The dataset returns 18000 plus records. Once the dataset has been populated I loop through and call a web-service to perform the update to the application database. My question is how could I go about performing this update in either smaller batches or smaller blocks or even using a progress bar. This is the function calling the web-service and running the update
public string InvokeSubmitCalendarValues()
{
try
{
DataWebService dataWebService = new DataWebService();
SubmitCalendarValuesRequest submitCalendarValuesRequest = new SubmitCalendarValuesRequest();
Credentials credentials = new Credentials();
credentials.Username = AmplaCodeUserName;
credentials.Password = AmplaCodeUserPassword;
credentials.Session = "";
submitCalendarValuesRequest.Credentials = credentials;
string rateUnit = "";
if (ds != null && ds.Tables.Count > 0)
{
foreach (DataTable dt in ds.Tables)
{
foreach (DataRow dr in dt.Rows)
{
SubmitCalendarValue[] values = new SubmitCalendarValue[1];
SubmitCalendarValue values_ = new SubmitCalendarValue();
values_.Name = dr["ItemName"].ToString();
values_.Value = dr["ItemValue"].ToString();
// Init DateTime object value = 2017-08-06T00:00:00.0000000+02:00
// We going to use DateTime ctor that takes Ticks
values_.StartDateTime = new System.DateTime(Convert.ToDateTime(dr["ActiveDateTime"]).Ticks);
if (dr["PeriodType"].ToString() != string.Empty || !(dr["Period"] is DBNull))
{
CalendarRate rate = new CalendarRate();
rateUnit = dr["PeriodType"].ToString();
rate.Count = Convert.ToInt32(dr["Period"]);
CalendarRateUnit cru = (CalendarRateUnit)Enum.Parse(typeof(CalendarRateUnit), rateUnit);
rate.Unit = cru;
values_.Rate = rate;
}
values[0] = values_;
submitCalendarValuesRequest.Values = values;
SubmitCalendarValuesResponse submitCalendarValuesResult = dataWebService.SubmitCalendarValues(submitCalendarValuesRequest);
}
}
}
}
catch(Exception ex)
{
return ex.Message.ToString();
}
return "Success";
}
You can do all these stuff in back-end thread and just pass it XML and call a thread and return message to end user.
or you can upload your XML to server and create a job that do batch process and you land user to processing view.
My application is used to copy tables from one database and duplicate them to another, I'm using smo and C#. My code:
private static void createTable(Table sourcetable, string schema, Server destinationServer,
Database db)
{
Table copiedtable = new Table(db, sourcetable.Name, schema);
createColumns(sourcetable, copiedtable);
copiedtable.AnsiNullsStatus = sourcetable.AnsiNullsStatus;
copiedtable.QuotedIdentifierStatus = sourcetable.QuotedIdentifierStatus;
copiedtable.TextFileGroup = sourcetable.TextFileGroup;
copiedtable.FileGroup = sourcetable.FileGroup;
copiedtable.Create();
}
private static void createColumns(Table sourcetable, Table copiedtable)
{
foreach (Column source in sourcetable.Columns)
{
Column column = new Column(copiedtable, source.Name, source.DataType);
column.Collation = source.Collation;
column.Nullable = source.Nullable;
column.Computed = source.Computed;
column.ComputedText = source.ComputedText;
column.Default = source.Default;
if (source.DefaultConstraint != null)
{
string tabname = copiedtable.Name;
string constrname = source.DefaultConstraint.Name;
column.AddDefaultConstraint(tabname + "_" + constrname);
column.DefaultConstraint.Text = source.DefaultConstraint.Text;
}
column.IsPersisted = source.IsPersisted;
column.DefaultSchema = source.DefaultSchema;
column.RowGuidCol = source.RowGuidCol;
if (server.VersionMajor >= 10)
{
column.IsFileStream = source.IsFileStream;
column.IsSparse = source.IsSparse;
column.IsColumnSet = source.IsColumnSet;
}
copiedtable.Columns.Add(column);
}
}
The project perfectly well works with North wind database, however, with some tables from AdventureWorks2014 database I get the following inner exception at copiedtable.Create();:
NullReferenceException: Object reference not set to an instance of an object.
I suspect, that AdventureWorks datetime column may be causing the problem (Data is entered like: 2008-04-30 00:00:00.000)
I have solved this problem myself and it was quite interesting. I couldn't find any null values neither in the Table itself, nor in it's columns.
Then I realized, that AdventureWorks2014 DB used User defined Data Types and XML Schema collections. As I haven't copied them, they couldn't be accessed and the creation of the table failed. It was only necessary to copy XML Schema Collections and User Defined Data Types to second database:
private static void createUserDefinedDataTypes(Database originalDB, Database destinationDB)
{
foreach (UserDefinedDataType dt in originalDB.UserDefinedDataTypes)
{
Schema schema = destinationDB.Schemas[dt.Schema];
if (schema == null)
{
schema = new Schema(destinationDB, dt.Schema);
schema.Create();
}
UserDefinedDataType t = new UserDefinedDataType(destinationDB, dt.Name);
t.SystemType = dt.SystemType;
t.Length = dt.Length;
t.Schema = dt.Schema;
try
{
t.Create();
}
catch(Exception ex)
{
throw (ex);
}
}
}
private static void createXMLSchemaCollections(Database originalDB, Database destinationDB)
{
foreach (XmlSchemaCollection col in originalDB.XmlSchemaCollections)
{
Schema schema = destinationDB.Schemas[col.Schema];
if (schema == null)
{
schema = new Schema(destinationDB, col.Schema);
schema.Create();
}
XmlSchemaCollection c = new XmlSchemaCollection(destinationDB, col.Name);
c.Text = col.Text;
c.Schema = col.Schema;
try
{
c.Create();
}
catch(Exception ex)
{
throw (ex);
}
}
}
I am trying to Insert/Add first value as "Select One" to my combobox in C# Windows Forms Application.
Combo box style is "DropDownList".
I am fetching cities data from database and binding combobox.
I know that I already set 1 datasource to combobox and again trying to add . I want to add "Select One" dynamically ,How to do this?
Here is the Filling cities code.
public void Fill_CitiesDDL()
{
try
{
cmbCity.Items.Clear();
DataSet ds = new DataSet();
ds = Select_Cities();
ds.DataSetName = "Tbl_City";
if (ds.Tables.Count > 0)
{
if (ds.DataSetName == "Tbl_City" && ds.Tables[0].Rows.Count > 0)
{
Dictionary<string, string> test = new Dictionary<string, string>();
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
test.Add(ds.Tables[0].Rows[i]["City_Name"].ToString(), ds.Tables[0].Rows[i]["City_Id"].ToString());
}
this.cmbCity.DataSource = new BindingSource(test, null);
this.cmbCity.DisplayMember = "Key";
this.cmbCity.ValueMember = "Value";
this.cmbCity.Items.Add("Select One ");--->Error is Coming at this Point
}
else
{
lblEmployerError.Text = "No data for City";
}
}
else
{
lblEmployerError.Text = "City Table does not exists";
}
}
catch (NullReferenceException nr)
{
lblEmployerError.Text="Null value exception caused, try again later..!!";
}
catch (SqlException sql1)
{
lblEmployerError.Text="Connection to server failed or network problem..!!";
}
catch (Exception ex)
{
lblEmployerError.Text="Fatal error catched, contact system administrator...!!";
}
}
Pls. give me solutions to this problem.
You will need to add your "Select One" value to the test dictionary prior to binding to the test as your data source.
test.Add("Select One ","Select One ");
then
this.cmbCity.DataSource = new BindingSource(test, null);
My code to use the function for updating is here and it works also
[HttpPost]
public bool SaveDefCompny(DefCompanyDTO DefCmpny)
{
using (RPDBEntities db = new RPDBEntities())
{
using (TransactionScope trans = new TransactionScope())
{
//the problem is here incase of saving
var UpdateDefCmpnyId = (from CmpnyId in db.DefCompanies
where CmpnyId.Id == DefCmpny.Id
select CmpnyId).First();
List<DefCompany> list = new List<DefCompany>();
list.Add(UpdateDefCmpnyId);
try
{
foreach (DefCompany DefCmpny1 in list)
{
DefCmpny1.Id = DefCmpny1.Id;
DefCmpny1.ShortName = DefCmpny.ShortName;
DefCmpny1.FullName = DefCmpny.FullName;
DefCmpny1.ContactPerson = DefCmpny.ContactPerson;
DefCmpny1.Address1 = DefCmpny.Address1;
DefCmpny1.CompanyCity = DefCmpny.CompanyCity;
DefCmpny1.CompanyState = DefCmpny.CompanyState;
DefCmpny1.CompanyCountry = DefCmpny.CompanyCountry;
DefCmpny1.ZipPostCode = DefCmpny.ZipPostCode;
DefCmpny1.TelArea = DefCmpny.TelArea;
DefCmpny1.CurrentCurrencyCode = DefCmpny.CurrentCurrencyCode;
db.SaveChanges();
trans.Complete();
}
}
catch (Exception ex)
{
}
}
return false;
}
}
when I try to save instead of updating the line of code
var UpdateDefCmpnyId = (from CmpnyId in db.DefCompanies
where CmpnyId.Id == DefCmpny.Id
select CmpnyId).First();
gives null value and hence saving fails because record is new and not present in database so how to handle null in case of saving how to use try catch so that when value is null it proceed to saving code that add
How about something along these lines:
var UpdateDefCmpnyId = (from CmpnyId in db.DefCompanies
where CmpnyId.Id == DefCmpny.Id
select CmpnyId).FirstOrDefault();
if(UpdateDefCmpnyId == null)
{
//insert
//(handle the id however you need to for insert. depending on your setup, you might be able to leave it empty and let the database put it in for you)
}
else
{
//update
//set the id as you do in the question
}
I am getting data from a mySql database and I am inserting it into another system. If a column has data in an incorrect format I log this and go to next row in the datatable. It works as expected but now if I have a search function in my method that gets some additional data and this function fails I want to immediately log this and go to next row. As it is now I just log it but it still gets inserted (without the value that didn't meet the search criteria).
My code:
private void updateCustomer()
{
MySqlConnection connection = new MySqlConnection("server=myServer;database=myDatabase;uid=myID;password=myPass");
MySqlCommand command = new MySqlCommand(#"mySelectCommand", connection);
DataTable customerTbl = new DataTable();
MySqlDataReader reader;
try
{
connection.Open();
reader = command.ExecuteReader();
if (reader.HasRows)
{
customerTbl.Load(reader);
}
reader.Close();
}
catch (Exception ex)
{
_out.error("Could not connect to mySql database");
}
finally
{
connection.Close();
}
foreach (DataRow row in customerTbl.Rows)
{
// Declare the customer variables
string customerID = Encoding.ASCII.GetString((byte[])row["Customer ID"]);
string ChildOf = row["Child of"].ToString();
// Create the customer object
Customer customer = new Customer();
customer.entityId = customerID;
if (ChildOf != "")
{
RecordRef parentRef = new RecordRef();
try
{
parentRef.internalId = searchCustomer(ChildOf);
}
catch
{
// If it fails here I want to log the customerID and then go to the next row in the datatable (could not find the internalid for ChildOf
_out.error(customerID + " was not updated. Error: invalid format Parent string");
}
finally
{
parentRef.typeSpecified = false;
customer.parent = parentRef;
}
}
// Invoke update() operation
WriteResponse response = _service.update(customer);
// Process the response
if (response.status.isSuccess)
{
}
else
{
_out.error(customerID + " was not updated. Error: " + getStatusDetails(response.status));
}
}
}
You need to remove the row in the catch block, and change the foreach loop to a backwards for loop to handle the removals.
I realized that I want to log the other failed fields as well. Maybe it's an inefficient way but I did something like:
bool findParent = true;
if (ChildOf != "")
{
try
{
RecordRef parentRef = new RecordRef();
parentRef.internalId = searchCustomer(ChildOf);
parentRef.typeSpecified = false;
customer.parent = parentRef;
}
catch
{
findParent = false;
_out.error(customerID + " was not inserted. Error: invalid format Parent string");
}
}
And then an if statement before trying to insert:
if (findPartner == true && findParent == true)
{
response = _service.add(customer);
// Process the response
if (response.status.isSuccess)
{
}
else
{
_out.error(customerID + " was not inserted. Error: " + getStatusDetails(response.status));
}
}
else
{
//_out.error(customerID + " was not updated. Error: " + getStatusDetails(response.status));
}
Use the row.HasError property.