I have the code below, where from 3 tables I take the data and write an xml.
I want write (when a record column has null value) the column on the xml with null value. For example if (Category_name == Null ) to write on the xml (Null) Right now the code skip the column and don’t even have this column on the xml.
string xmlFileData = "";
string[] tables = new string[] { "category", "company", "config" };
string query;
xmlFileData += "<MyXml>";
SqlConnection conn;
dbconnect obj;
obj = new dbconnect();//initailizing class object
for (int i = 0; i < tables.Length; i++)
{
string ifemptquery;
DataSet ds = new DataSet();
DataSet ds1 = new DataSet();
conn = obj.getConnection(); //calling connection function
ifemptquery = "SELECT * FROM " + tables[i] ";
SqlCommand cmd1 = new SqlCommand(ifemptquery, conn);
conn.Open();
SqlDataAdapter da1 = new SqlDataAdapter(cmd1);
DataTable dt1 = new DataTable();
da1.Fill(dt1);
conn.Close();
if (dt1.Rows.Count > 0)
{
query = "SELECT * FROM " + tables[i] ";
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
conn.Close();
conn.Dispose();
ds.DataSetName = tables[i];
string vartbname = tables[i];
string trimed_tbname = vartbname.Replace("_", "");
ds.Tables[0].TableName = trimed_tbname;
xmlFileData += ds.GetXml();
}
else
{
}
}
xmlFileData += "</MyXml>";
File.WriteAllText(Server.MapPath("~/xmlbackup/") + "Backup.xml", xmlFileData);
I have been searching the whole world for a solution of writing null fields to XML using DataSet.WriteXML(). The answer posted by Vlad is the one I also used in my project but I found that following works in a much more performance optimized way. I have created a function for your convenience. Change your dataset tables one after the other by calling the following function and replacing the tables.
private DataTable GetNullFilledDataTableForXML(DataTable dtSource)
{
// Create a target table with same structure as source and fields as strings
// We can change the column datatype as long as there is no data loaded
DataTable dtTarget = dtSource.Clone();
foreach (DataColumn col in dtTarget.Columns)
col.DataType = typeof(string);
// Start importing the source into target by ItemArray copying which
// is found to be reasonably fast for nulk operations. VS 2015 is reporting
// 500-525 milliseconds for loading 100,000 records x 10 columns
// after null conversion in every cell which may be usable in many
// circumstances.
// Machine config: i5 2nd Gen, 8 GB RAM, Windows 7 64bit, VS 2015 Update 1
int colCountInTarget = dtTarget.Columns.Count;
foreach (DataRow sourceRow in dtSource.Rows)
{
// Get a new row loaded with data from source row
DataRow targetRow = dtTarget.NewRow();
targetRow.ItemArray = sourceRow.ItemArray;
// Update DBNull.Values to empty string in the new (target) row
// We can safely assign empty string since the target table columns
// are all of string type
for (int ctr = 0; ctr < colCountInTarget; ctr++)
if (targetRow[ctr] == DBNull.Value)
targetRow[ctr] = String.Empty;
// Now add the null filled row to target datatable
dtTarget.Rows.Add(targetRow);
}
// Return the target datatable
return dtTarget;
}
Refer similar question here - dataSet.GetXml() doesn't return xml for null or blank columns
Apart from solutions mentioned there, you can also traverse through dataset and write XML using XmlTextWriter. This method is not recommended if you are dealing with huge data.
Related
The following C# code runs a DAX statement and retrieves a DataTable. This works fine, but now I need to retrieve from the database up to N rows. Is there a way to limit the number of rows returned by the Fill function? If not, how can I retrieve the top N rows? Note that I need to keep this generic for any DAX statement, so you shouldn't change the DAX itself. Also, I don't want to retrieve all the data and then take the first N rows as the data may be too large.
public static DataTable runDaxStatement(int maxRows) {
var con = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
AdomdConnection conn = new AdomdConnection(con);
DataSet ds = new DataSet();
ds.EnforceConstraints = false;
AdomdCommand cmd = new AdomdCommand("evaluate customers", conn);
AdomdDataAdapter da = new AdomdDataAdapter(cmd);
da.Fill(ds);
return ds.Tables[0];
}
Came across the following TOPN function in the documentation.
This can be used to return the top N rows of the specified table.
For example
public static DataTable runDaxStatement(int maxRows) {
var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString;
using(AdomdConnection connection = new AdomdConnection(connectionString)) {
string commandText = $"EVALUATE TOPN({maxRows}, customers, <orderBy_expression_here>)";
AdomdCommand command = connection.CreateCommand();
command.CommandText = commandText;
DataSet dataSet = new DataSet(){
EnforceConstraints = false
}
AdomdDataAdapter adapter = new AdomdDataAdapter(command);
adapter.Fill(dataSet);
return dataSet.Tables[0];
}
}
I am receiving this sql error there is no row at position - 1.
This is what I have done.
void showData(int index)
{
Connection con = new OrderManager.Connection();
SqlDataAdapter sda = new SqlDataAdapter("Select * from [MasterDatabase].[dbo].[Neworder] Where OrderID = '" + TxtBox_OrderID.Text + "'", con.ActiveCon());
dt = new DataTable();
sda.Fill(dt);
TxtBox_OrderID.Text = dt.Rows[index][0].ToString();
ClearTextBoxes();
dataGridView1.Rows.Clear();
foreach (DataRow item in dt.Rows)
{
int n = dataGridView1.Rows.Add();
dataGridView1.Rows[n].Cells[0].Value = item["OrderID"].ToString();
dataGridView1.Rows[n].Cells[1].Value = item["Date"].ToString();
dataGridView1.Rows[n].Cells[2].Value = item["Customer_Name"].ToString();
dataGridView1.Rows[n].Cells[3].Value = item["ProductID"].ToString();
dataGridView1.Rows[n].Cells[4].Value = item["Product_Name"].ToString();
dataGridView1.Rows[n].Cells[5].Value = item["Product_Color"].ToString();
dataGridView1.Rows[n].Cells[6].Value = item["Product_PCs"].ToString();
dataGridView1.Rows[n].Cells[7].Value = item["Product_Cutting"].ToString();
dataGridView1.Rows[n].Cells[8].Value = item["Product_TotalYards"].ToString();
}
label12.Text = "Row Count: " + dt.Rows.Count.ToString();
}
I want to display only those records while navigating whose OrderID is equals to the order ID in the database.
I think your error happens on this line
TxtBox_OrderID.Text = dt.Rows[index][0].ToString();
this is not an SQL error but a simple index out of the bounds of the array.
For some reasons, when you try to use a row that is not included in the Rows collection of the datatable you get this error message instead of the less ambiguous IndexOutOfRangeException. This message comes if you pass some value for the index variable that is less than zero or bigger than the number of rows in the datatable dt.
You don't have any check on the number of rows returned by the query and thus is possible that your query doesn't return any record or simple the value of index is -1
void showData(int index)
{
Connection con = new OrderManager.Connection();
SqlDataAdapter sda = new SqlDataAdapter(".......", con.ActiveCon());
dt = new DataTable();
sda.Fill(dt);
// Protect the access to the rows collection of the table...
if(index < dt.RowsCount && index >= 0)
{
TxtBox_OrderID.Text = dt.Rows[index][0].ToString();
// the code that fills the datagrid
}
else
{
// Message for your user about a record not found
}
}
As a side note, please follow ASAP the advice given to parameterize your query. You will avoid Sql Injection and parsin problems
I'm trying to write data back into a file on Unidata, after the contents have been adjusted in a datagridview.
I've tried various option based around the code below, but with no luck.
Within the foreach section I want to update my file.
The file consists of 10 single value attributes.
I tried fl.write(),but get an error relating to writing to a null value...
try
{
DataTable modifiedTable = m_DS.Tables[0].GetChanges(DataRowState.Modified);
if (modifiedTable.Rows.Count > 0)
{
U2Connection con = GetConnection();
Console.WriteLine("Connected.................");
UniSession lUniSession = con.UniSession;
UniFile fl = lUniSession.CreateUniFile("myTableName");
UniDynArray udr3 = new UniDynArray(lUniSession);
foreach (DataRow item in modifiedTable.Rows)
{
}
con.Close();
}
}
Thank you for using UniObjects’s API of U2 Toolkit for .NET (formerly known as standalone UO.NET).
Yesterday (June 10th, 2014) , we have Released U2 Toolkit for .NET v2.1.0. Main features of U2 Toolkit for .NET v2.1.0 is
Native Visual Studio Integration
For other features, see this link
http://blog.rocketsoftware.com/2014/05/access-nosql-data-using-sql-syntax-u2-toolkit-net-v2-1-0-beta/
Can you please try the same code ( 10 single value attributes) using SELECT and UPDATE. For your information, SELECT and UPDATE behind the scene calls UniFile Read and Write. These Samples are part of the installation. Go to these directories.
C:\Program Files (x86)\Rocket Software\U2 Toolkit for .NET\U2 Database Provider\samples\C#\UniData\NativeAccess\Select_SQL_Syntax
C:\Program Files (x86)\Rocket Software\U2 Toolkit for .NET\U2 Database Provider\samples\C#\UniData\NativeAccess\Update_SQL_Syntax
SELECT
private static void Select()
{
try
{
Console.WriteLine(Environment.NewLine + "Start...");
ConnectionStringSettingsCollection settings = ConfigurationManager.ConnectionStrings;
ConnectionStringSettings cs = settings["u2_connection"];
U2Connection lConn = new U2Connection();
lConn.ConnectionString = cs.ConnectionString;
lConn.Open();
Console.WriteLine("Connected...");
U2Command cmd = lConn.CreateCommand();
//ID,FNAME,LNAME : Single Value
//SEMESTER: Multi Value
//COURSE_NBR,COURSE_GRD: MS
cmd.CommandText = string.Format("SELECT ID,FNAME,LNAME,SEMESTER,COURSE_NBR,COURSE_GRD FROM STUDENT WHERE ID > 0 ORDER BY ID");
U2DataAdapter da = new U2DataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
Console.WriteLine(Environment.NewLine);
ds.WriteXml(Console.Out);
lConn.Close();
Console.WriteLine(Environment.NewLine + "End...");
Console.WriteLine(SUCCESS_MSG);
}
catch (Exception e2)
{
string lErr = e2.Message;
if (e2.InnerException != null)
{
lErr += lErr + e2.InnerException.Message;
}
Console.WriteLine(Environment.NewLine + lErr);
Console.WriteLine(FAIL_MSG);
}
}
Update
private static void Update_Using_DataSet()
{
try
{
Console.WriteLine(Environment.NewLine + "Start...");
ConnectionStringSettingsCollection settings = ConfigurationManager.ConnectionStrings;
ConnectionStringSettings cs = settings["u2_connection"];
U2Connection lConn = new U2Connection();
lConn.ConnectionString = cs.ConnectionString;
lConn.Open();
Console.WriteLine("Connected...");
U2Command cmd = lConn.CreateCommand();
//ID,FNAME,LNAME : Single Value
//SEMESTER: Multi Value
//COURSE_NBR,COURSE_GRD: MS
cmd.CommandText = string.Format("SELECT ID,FNAME,LNAME,SEMESTER,COURSE_NBR,COURSE_GRD FROM STUDENT WHERE ID={0} ORDER BY ID",ID);
U2DataAdapter da = new U2DataAdapter(cmd);
U2CommandBuilder builder = new U2CommandBuilder(da);
da.UpdateCommand = builder.GetUpdateCommand();
DataSet ds = new DataSet();
da.Fill(ds);
DataTable dt = ds.Tables[0];
DataRowCollection lDataRowCollection = dt.Rows;
int i = 1;
foreach (DataRow item in lDataRowCollection)
{
item["FNAME"] = item["FNAME"] + "3";// modify single value
item["SEMESTER"] = item["SEMESTER"] + "$";//modify multi-value
item["COURSE_GRD"] = item["COURSE_GRD"] + "$";
i++;
}
da.Update(ds);//use DataAdapter's Update() API
//print modified value
cmd.CommandText = string.Format("SELECT ID,FNAME,LNAME,SEMESTER,COURSE_NBR,COURSE_GRD FROM STUDENT WHERE ID={0} ORDER BY ID", ID); ;
//verify the change
U2DataAdapter da2 = new U2DataAdapter(cmd);
DataSet ds2 = new DataSet();
da2.Fill(ds2);
Console.WriteLine(Environment.NewLine);
ds2.WriteXml(Console.Out);
//close connection
lConn.Close();
Console.WriteLine(Environment.NewLine + "End...");
Console.WriteLine(SUCCESS_MSG);
}
catch (Exception e2)
{
Console.WriteLine(FAIL_MSG);
string lErr = e2.Message;
if (e2.InnerException != null)
{
lErr += lErr + e2.InnerException.Message;
}
Console.WriteLine(Environment.NewLine + lErr);
}
}
You will need to modify the UniDynArray (the record) for each row value in the table and then write the UniDynArray to the file and specific record id:
for (Int32 i=0; i < modifiedTable.Rows.Count; i++)
{
DataRow item = modifiedTable.Rows[i];
//Modify each attribute in the record from the rows in the table
udr3.Replace(i+1, (String)item[0]);
}
//Write the modified record to the file
fl.Write("MyRecordId", udr3);
The reason you got the null reference exception is because you didn't assign a value to fl.RecordId or fl.Record before calling fl.Write(). As you can see above, I prefer to use the overload of the Write method that takes record id and record data as parameters instead of setting the properties on the instance of UniFile.
I have excel file and loaded in c# windows applciaction.
I want to change the value in excel cell e.g change value in cell a10 and save the file.
The excel file contains multiple sheets.
Any help in this regard?
var ds = new DataSet();
ds = Parse(fileName);
static DataSet Parse(string fileName)
{
string connectionString = string.Format("provider=Microsoft.Jet.OLEDB.4.0; data source={0};Extended Properties=Excel 8.0;", fileName);
DataSet data = new DataSet();
foreach (var sheetName in GetExcelSheetNames(connectionString))
{
using (OleDbConnection con = new OleDbConnection(connectionString))
{
var dataTable = new DataTable();
string query = string.Format("SELECT * FROM [{0}]", sheetName);
con.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter(query, con);
adapter.Fill(dataTable);
data.Tables.Add(dataTable);
}
}
return data;
}
static string[] GetExcelSheetNames(string connectionString)
{
OleDbConnection con = null;
DataTable dt = null;
con = new OleDbConnection(connectionString);
con.Open();
dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
if (dt == null)
{
return null;
}
String[] excelSheetNames = new String[dt.Rows.Count];
int i = 0;
foreach (DataRow row in dt.Rows)
{
excelSheetNames[i] = row["TABLE_NAME"].ToString();
i++;
}
return excelSheetNames;
}
}
To specify that your sheet has a header row or not, modify the connection string to specify the HDR value. Refer to http://www.connectionstrings.com/excel/ for more information.
If your sheet has a header row, you can refer the columns by the header.
If your sheet does not have a header row use F1, F2, F3.... Fn where F1 is the first selected column. If you don't specify where to start, then column A, B, C correspond to F1, F2, F3 etc.
e.g.
SELECT * FROM [Sheet1$] <-- Column A=F1, B=F2 etc.
SELECT * FROM [Sheet1$B1:Z100] <-- Column B=F1, C=F2 etc.
Now once you know how to refer to the columns, rest should be easy. Create an OledbCommand object and execute your command.
UPDATE [Sheet1$A1:A1] SET F1='TestValue1' <-- trick to update only one cell
UPDATE [Sheet1$] SET F1='TestValue1', F2 = 'some value 2' WHERE WhateverCondition
I haven't ever tried with Datasets and DataAdapters with excel oledb, but logically that should work too because in the end they all drill down to Command object.
I'm looking at the example here:
http://msdn.microsoft.com/en-US/library/y06xa2h1(v=vs.80).aspx
string s = "primaryKeyValue";
DataRow foundRow = dataSet1.Tables["AnyTable"].Rows.Find(s);
if (foundRow != null)
{
MessageBox.Show(foundRow[1].ToString());
}
else
{
MessageBox.Show("A row with the primary key of " + s + " could not be found");
}
They don't specify where does dataSet1 come from and does this represent some database?
I'm trying to use this example in my code to find unique rows but I can't seem to implement this syntax. I'm only using connection string to open connection to SQL and I use SqlDataAdapter to perform functions...
EDIT:
SqlConnection myConnection = new SqlConnection("Data Source=server; Initial Catalog=Dashboard; Integrated Security=SSPI; Persist Security Info=false; Trusted_Connection=Yes");
SqlDataAdapter da = new SqlDataAdapter();
try
{
//Opens the connection to the specified database
myConnection.Open();
//Specifies where the Table in the database where the data will be entered and the columns used
da.InsertCommand = new SqlCommand("INSERT INTO DashboardLibAnswer(Id,Date,Time,Question,Details,Answer,Notes,EnteredBy,WhereReceived,QuestionType,AnswerMethod,TransactionDuration)"
+ "VALUES(#Id,#Date,#Time,#Question,#Details,#Answer,#Notes,#EnteredBy,#WhereReceived,#QuestionType,#AnswerMethod,#TransactionDuration)", myConnection);
//Specifies the columns and their variable type where the data will be entered
//Special note: Conversion from String > DateTime will cause exceptions that will only import some part of data and not everything
da.InsertCommand.Parameters.Add("#Id", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#Date", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Time", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Question", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Details", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Answer", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#Notes", SqlDbType.Text);
da.InsertCommand.Parameters.Add("#EnteredBy", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#WhereReceived", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#QuestionType", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#AnswerMethod", SqlDbType.NVarChar);
da.InsertCommand.Parameters.Add("#TransactionDuration", SqlDbType.NVarChar);
//Using the global variable counter this loop will go through each valid entry and insert it into the specifed database/table
for (int i = 0; i < counter; i++)
{
//Iterates through the collection array starting at first index and going through until the end
//and inserting each element into our SQL Table
DataSet dashboardDS = new DataSet();
da.Fill(dashboardDS, "DashboardLibAnswer");
DataTable dt = dashboardDS.Tables["DashboardLibAnswer"];
foreach (DataColumn col in dt.Columns)
{
if (col.Unique)
{
da.InsertCommand.Parameters["#Id"].Value = collection.getIdItems(i);
da.InsertCommand.Parameters["#Date"].Value = collection.getDateItems(i);
da.InsertCommand.Parameters["#Time"].Value = collection.getTimeItems(i);
da.InsertCommand.Parameters["#Question"].Value = collection.getQuestionItems(i);
da.InsertCommand.Parameters["#Details"].Value = collection.getDetailsItems(i);
da.InsertCommand.Parameters["#Answer"].Value = collection.getAnswerItems(i);
da.InsertCommand.Parameters["#Notes"].Value = collection.getNotesItems(i);
da.InsertCommand.Parameters["#EnteredBy"].Value = collection.getEnteredByItems(i);
da.InsertCommand.Parameters["#WhereReceived"].Value = collection.getWhereItems(i);
da.InsertCommand.Parameters["#QuestionType"].Value = collection.getQuestionTypeItems(i);
da.InsertCommand.Parameters["#AnswerMethod"].Value = collection.getAnswerMethodItems(i);
da.InsertCommand.Parameters["#TransactionDuration"].Value = collection.getTransactionItems(i);
da.InsertCommand.ExecuteNonQuery();
}
}
//Updates the progress bar using the i in addition to 1
_worker.ReportProgress(i + 1);
} // end for
//Once the importing is done it will show the appropriate message
MessageBox.Show("Finished Importing");
} // end try
catch (Exception exceptionError)
{
//To show exceptions thrown just uncomment bellow line
//rtbOutput.AppendText(exceptionError.ToString);
} // end catch
//Closes the SQL connection after importing is done
myConnection.Close();
}
if you populate a dataset from your data adapter, you'll be able to follow the same logic -
http://msdn.microsoft.com/en-us/library/bh8kx08z(v=vs.71).aspx
It might be worth showing what you actually have to get more specific help
EDIT
I think I'm understanding what you want - if you fill your datatable from the already populated table, just check the item doesn't already exist before adding it - i.e.
if (dt.Rows.Find(collection.getIdItems(i)) == null)
{
// add your new row
}
(just to be sure I knocked together a quick test - hopefully this helps):
// MyContacts db has a table Person with primary key (ID) - 3 rows - IDs 4,5,6
SqlConnection myConnection = new SqlConnection("Data Source=.; Initial Catalog=MyContacts; Integrated Security=SSPI; Persist Security Info=false; Trusted_Connection=Yes");
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = new SqlCommand("select * from Person", myConnection);
myConnection.Open();
DataSet dashboardDS = new DataSet();
da.Fill(dashboardDS, "Person");
dashboardDS.Tables[0].PrimaryKey = new[] { dashboardDS.Tables[0].Columns["ID"]};
List<int> ids = new List<int> {4, 6, 7};
foreach (var id in ids)
{
if (dashboardDS.Tables[0].Rows.Find(id) == null)
{
Console.WriteLine("id not in database {0}", id); //i.e. 7
}
}
You will first need to open a connection to your database. This is an excellent source for connection strings: The Connection String Reference.
Then you will need to fill the dataset with data from some table. Since we are only interested in the schema information we are only selecting one row (SELECT TOP 1 ...).
Then we can go through the columns and check their Unique property (Boolean):
string connString =
"server=(local)\\SQLEXPRESS;database=MyDatabase;Integrated Security=SSPI";
string sql = #"SELECT TOP 1 * FROM AnyTable";
using (SqlConnection conn = new SqlConnection(connString)) {
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(sql, conn);
using (DataSet ds = new DataSet()) {
da.Fill(ds, "AnyTable");
DataTable dt = ds.Tables["AnyTable"];
foreach (DataColumn col in dt.Columns) {
if (col.Unique) {
Console.WriteLine("Column {0} is unique.", col.ColumnName);
}
}
}
}
UPDATE #1
Sorry, I missunderstood your question. The above example returns unique columns, not unique rows. You can get unique (distinct) rows by using the DISTINCT keyword in SQL:
SELECT DISTINCT field1, field2, field3 FROM AnyTable
You can then fill the data table the same way as above.
Usually the word "unique" is used for unique constraints and unique indexes in database jargon. The term "distinct" is used for rows which are different.
UPDATE #2
Your updated question seems to suggest that you don't want find unique rows, but that you want to insert unique rows (which is the exact opposite).
Usually you would select distinct items from a collection like this. However it is difficult to answer your question accurately, since we don't know the type of your collection.
foreach (var item in collection.Distinct()) {
}
UPDATE #3
The easiest way to insert distinct values in the SQL Server table is to filter the rows at their origin, when reading them from the CSV-File; even before splitting them.
string[] lines = File.ReadAllLines(#"C:\Data\MyData.csv");
string[][] splittedLines = lines
.Distinct()
.Select(s => s.Split(','))
.ToArray();
Now you have distinct (unique) splitted lines that you can insert into the SQL Server table.