SQLite reports insert query error even though the row inserted - c#

I am using http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki version 1.0.82.0
When I insert a row like so:
"INSERT INTO [testtable] (col1,col2) values ('','')"
I always get a result of 1 from SQLiteCommand.ExecuteNonQuery(); where it should be returning 0 (OK) or 101 (DONE). I know the row is getting inserted just fine because the auto increment value increases each time I run the method.
The class
readonly object _threadlock = new object();
readonly string _file;
public CSQLite(string file)
{
_file = file;
}
private SQLiteConnection _sqlCon;
private SQLiteCommand _sqlCmd;
private SQLiteDataAdapter _db;
private void SetConnection()
{
lock (_threadlock)
{
_sqlCon = new SQLiteConnection(String.Format("Data Source={0};Version=3;New=False;Compress=True;", _file));
}
}
public int SimpleInsertAndGetlastID(out int id)
{
lock (_threadlock)
{
SetConnection();
_sqlCon.Open();
//Execute
_sqlCmd = _sqlCon.CreateCommand();
_sqlCmd.CommandText = "INSERT INTO [testtable] (col1,col2) values ('','')";
var res = _sqlCmd.ExecuteNonQuery();
//Get id
_db = new SQLiteDataAdapter("select last_insert_rowid();", _sqlCon);
var ds = new DataSet();
_db.Fill(ds);
DataTable dt = ds.Tables[0];
var val = dt.Rows[0][0].ToString();
Int32.TryParse(val, out id);
_sqlCon.Close();
return res;
}
}
The Test:
/// <summary>
///A test for SimpleInsertAndGetlastID
///</summary>
[TestMethod()]
public void SimpleInsertAndGetlastIDTest()
{
var file = "dbs\\test.db";
var target = new CSQLite(file);
var id = -1;
var res = -1;
try
{
res = target.SimpleInsertAndGetlastID(out id);
}
catch (Exception ex){/*Breakpoint*/}
Assert.IsTrue(id > 0); //id gets +1 every time the test is run so the row *is* getting inserted
Assert.IsTrue(res==0||res==101); //Res is always 1 for some reason
}
Table creation (in case that's the problem):
public List<string> Columns { get; set; }
if (!File.Exists(_dbFile))
SQLiteConnection.CreateFile(_dbFile);
var fieldqry = "";
var count = 0;
Columns.ForEach((field) =>
{
count++;
fieldqry += String.Format("[{0}] TEXT NULL", field);
if (count < Columns.Count)
fieldqry += ",";
});
var qry = String.Format("CREATE TABLE IF NOT EXISTS [{0}](" +
"[ID] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
"{1}" +
");", TableName, fieldqry);
var sql = new CSQLite(_dbFile);
var res = sql.Execute(qry);
if(res!=SqLiteErrorCodes.SQLITE_OK)
throw new SqLiteImplementationException("Query failed.");
Where columns is new List<string> { "col1", "col2" } };
Can anyone tell me what I did wrong?

ExecuteNonQuery() does not return a SQLite error code, it returns the number of rows affected by the query. If you are inserting a row, 1 sounds like the expected result if the operation was successful.

The result from ExecuteNonQuery is concidered as "number of rows affected" and not an error code :-)

Related

'DataTable' does not contain a public instance definition for 'GetEnumerator'

I am trying to get result from DataTable but I am stuck and have no idea what to do.
I have public static DataTable VratiKorisnike() which needs to return DataTable resultTable as result because my result is store in resultTable.
SO far my function is here
public static DataTable VratiKorisnike()
{
List<Korisnik> lstADUsers = new List<Korisnik>();
string sDomainName = "saos";
string DomainPath = "LDAP://" + sDomainName;
string output = #"C:\output.txt";
DirectoryEntry searchRoot = new DirectoryEntry(DomainPath);
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.Filter = "(&(objectClass=user)(objectCategory=person))";
search.PropertiesToLoad.Add("samaccountname");
search.PropertiesToLoad.Add("usergroup");
search.PropertiesToLoad.Add("displayname");
search.PropertiesToLoad.Add("userAccountControl");
search.PropertiesToLoad.Add("PasswordExpirationDate");
//search.PropertiesToLoad.Add("DomainGroup");
DataTable resultsTable = new DataTable();
resultsTable.Columns.Add("samaccountname");
resultsTable.Columns.Add("usergroup");
resultsTable.Columns.Add("displayname");
resultsTable.Columns.Add("userAccountControl");
resultsTable.Columns.Add("PasswordExpirationDate");
//resultsTable.Columns.Add("DomainGroup");
SearchResult result;
SearchResultCollection resultCol = search.FindAll();
if (resultCol != null)
{
for (int counter = 0; counter <= (resultCol.Count - 1); counter++)
{
string UserNameEmailString = string.Empty;
result = search.FindOne();
if ((result.Properties.Contains("samaccountname") && result.Properties.Contains("usergroup")))
{
Korisnik korisnik = new Korisnik();
korisnik.Ime = ((string)(result.Properties["samaccountname"][0]));
korisnik.Prezime = ((string)(result.Properties["displayname"][0]));
korisnik.AccountExpired = (DateTime)result.Properties["userAccountControl"][0];
korisnik.PassNevExp = ((bool)result.Properties["PasswordExpirationDate"][0]);
korisnik.DomenskaGrupa = ((string)(result.Properties["DomainGroup"][0]));
DataRow dr = resultsTable.NewRow();
dr["samaccountname"] = korisnik.Ime;
dr["displayname"] = korisnik.Prezime;
dr["userAccountControl"] = korisnik.AccountExpired;
dr["PasswordExpirationDate"] = korisnik.PassNevExp;
dr["DomainGroup"] = korisnik.DomenskaGrupa;
resultsTable.Rows.Add(dr);
lstADUsers.Add(korisnik);
}
}
var json = JsonConvert.SerializeObject(resultCol, Formatting.Indented);
var res = json;
Console.WriteLine(resultCol);
Console.ReadLine();
File.WriteAllText(output, json);
}
return resultsTable;
}
When I call function to Main I get error
Foreach statement cannot operate on variables of type 'DataTable'
because 'DataTable' does not contain a public instance definition for
'GetEnumerator'
foreach (Korisnik korisnik in VratiKorisnike())
{
Console.WriteLine(korisnik);
}
I try something like this:
foreach(DataTable dt in VratiKorisnike())
{
Console.WriteLine(dt);
}
The error is VratiKorisnike()
Any idea how to resolve this issue ?
To use a DataTable as an IEnumerable<DataRow>, you need to use Linq To DataSet, in perticular AsEnumerable
foreach (DataRow row in VratiKorisnike().AsEnumerable())
{
string displayName = row.Field<string>("displayname")
...
}
You need to use the Rows property:
foreach (var korisnik in VratiKorisnike().Rows)
It Represents a collection of rows for a DataTable, and . Actually it will compiles like this and as you can see, because of GetEnumerator you can use your loop with that:
IEnumerator enumerator = VratiKorisnike().Rows.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
DataRow value = (DataRow)enumerator.Current;
Console.WriteLine(value);
}
}
finally
{
IDisposable disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}

how to separate the "collection" from creating and adding a new instance of "lookaheadRunInfo"

I am trying to "collect" the GetString(2) until GetString(0) changes,so am trying to find out how to separate the "collection" from creating and adding a new instance of "lookaheadRunInfo"?I have tried as below which throws an exception
System.NullReferenceException was unhandled by user code at line
lookaheadRunInfo.gerrits.Add(rdr.GetString(1)); ,can anyone provide guidance on how to fix this issue?
try
{
Console.WriteLine("Connecting to MySQL...");
conn.Open();
string sql = #"select lr.ec_job_link, cl.change_list ,lr.submitted_by, lr.submission_time,lr.lookahead_run_status
from lookahead_run as lr, lookahead_run_change_list as lrcl, change_list_details as cld,change_lists as cl
where lr.lookahead_run_status is null
and lr.submission_time is not null
and lrcl.lookahead_run_id = lr.lookahead_run_id
and cl.change_list_id = lrcl.change_list_id
and cl.change_list_id not in (select clcl.change_list_id from component_labels_change_lists as clcl)
and cld.change_list_id = lrcl.change_list_id
group by lr.lookahead_run_id, cl.change_list
order by lr.submission_time desc
limit 1000
";
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
var ECJoblink_previous ="";
var gerritList = new List<String>();
while (rdr.Read())
{
//Console.WriteLine(rdr[0] + " -- " + rdr[1]);
//Console.ReadLine();
var lookaheadRunInfo = new LookaheadRunInfo();
lookaheadRunInfo.ECJobLink = rdr.GetString(0);
if (ECJoblink_previous == lookaheadRunInfo.ECJobLink)
{
//Keep appending the list of gerrits until we get a new lookaheadRunInfo.ECJobLink
lookaheadRunInfo.gerrits.Add(rdr.GetString(1));
}
else
{
lookaheadRunInfo.gerrits = new List<string> { rdr.GetString(1) };
}
ECJoblink_previous = lookaheadRunInfo.ECJobLink;
lookaheadRunInfo.UserSubmitted = rdr.GetString(2);
lookaheadRunInfo.SubmittedTime = rdr.GetString(3).ToString();
lookaheadRunInfo.RunStatus = "null";
lookaheadRunInfo.ElapsedTime = (DateTime.UtcNow-rdr.GetDateTime(3)).ToString();
lookaheadRunsInfo.Add(lookaheadRunInfo);
}
rdr.Close();
}
catch
{
throw;
}
If I understand your requirements correctly, you wish to keep a single lookaheadRunInfo for several rows of the resultset, until GetString(0) changes. Is that right?
In that case you have some significant logic problems. The way it is written, even if we fix the null reference, you will get a new lookaheadRunInfo with each and every row.
Try this:
string ECJoblink_previous = null;
LookAheadRunInfo lookaheadRunInfo = null;
while (rdr.Read())
{
if (ECJoblink_previous != rdr.GetString(0)) //A new set of rows is starting
{
if (lookaheadRunInfo != null)
{
lookaheadRunsInfo.Add(lookaheadRunInfo); //Save the old group, if it exists
}
lookaheadRunInfo = new LookAheadRunInfo //Start a new group and initialize it
{
ECJobLink = rdr.GetString(0),
gerrits = new List<string>(),
UserSubmitted = rdr.GetString(2),
SubmittedTime = rdr.GetString(3).ToString(),
RunStatus = "null",
ElapsedTime = (DateTime.UtcNow-rdr.GetDateTime(3)).ToString()
}
}
lookahead.gerrits.Add(rdr.GetString(1)); //Add current row
ECJoblink_previous = rdr.GetString(0); //Keep track of column 0 for next iteration
}
if (lookaheadRunInfo != null)
{
lookaheadRunsInfo.Add(lookaheadRunInfo); //Save the last group, if there is one
}
The idea here is:
Start with a blank slate, nothing initialized
Monitor column 0. When it changes (as it will on the first row), save any old list and start a new one
Add to current list with each and every iteration
When done, save any remaining items in its own list. A null check is required in case the reader returned 0 rows.

How to set column Properties in SQL Server

I have to create a Copy of a Database on SQL Server.
On this way I got a connection to the new DB
ADODB.Connection connection = new ADODB.Connection();
OleDbConnectionStringBuilder builder = new System.Data.OleDb.OleDbConnectionStringBuilder();
builder["Provider"] = provider;
builder["Server"] = #"Themis\DEV";
builder["Database"] = file_name;
builder["Integrated Security"] = "SSPI";
string connection_string = builder.ConnectionString;
connection.Open(connection_string, null, null, 0);
return connection;
}
I create the tables with ADOX
ADOX.Catalog cat, Dictionary<string, ADOX.DataTypeEnum> columntype)
{
List<string> primaryKeysList = GetPrimaryKey(tabelle);
Key priKey = new Key();
Catalog catIn = new Catalog();
catIn.ActiveConnection = dbInfo.ConIn;
Dictionary<string, List<string>> indexinfo = new Dictionary<string, List<string>>();
GetSecondaryIndex(tabelle, indexinfo);
if (columntype.Count != 0) columntype.Clear();
if (size.Count != 0) size.Clear();
foreach (DataRow myField in schemaTable.Rows)
{
String columnNameValue = myField[columnName].ToString(); //SpaltenName
bool ich_darf_dbnull_sein = (bool)myField["AllowDBNull"];
ADOX.Column columne = new ADOX.Column();
columne.ParentCatalog = cat;
columne.Name = columnNameValue;
if (!columntype.ContainsKey(columnNameValue))
{
columntype.Add(columnNameValue, (ADOX.DataTypeEnum)myField["ProviderType"]);
}
columne.Type = (ADOX.DataTypeEnum)myField["ProviderType"];
//type.Add((ADODB.DataTypeEnum)myField["ProviderType"]);
columne.DefinedSize = (int)myField["ColumnSize"];
dbInfo.ColumnName = columnNameValue;
dbInfo.TableName = tabelle;
dbInfo.Column_size = (int)myField["ColumnSize"];
dbInfo.Column_Type = (ADOX.DataTypeEnum)myField["ProviderType"];
size.Add((int)myField["ColumnSize"]);
if (primaryKeysList.Contains(columnNameValue))
{
dbInfo.IsPrimary = true;
}
else dbInfo.IsPrimary = false;
object index = catIn.Tables[tabelle].Columns[columnNameValue].Attributes;
if (index.Equals(ColumnAttributesEnum.adColFixed) || (int)index == 3)
dbInfo.Fixed_length = true;
else
dbInfo.Fixed_length = false;
Console.WriteLine("{0}={1}", myField[columnName].ToString(), catIn.Tables[tabelle].Columns[columnNameValue].Attributes);
TargetDBMS.SetColumnProperties(columne, dbInfo);
switch (columne.Type)
{
case ADOX.DataTypeEnum.adChar:
case ADOX.DataTypeEnum.adWChar:
case ADOX.DataTypeEnum.adVarChar:
case ADOX.DataTypeEnum.adVarWChar:
columne.DefinedSize = (int)myField["ColumnSize"];
break;
default:
break;
}
if (primaryKeysList.Contains(columnNameValue))
{
priKey.Name = "PK_" + tabelle + "_" + columnNameValue;
primaryKeysList.Remove(columnNameValue);
priKey.Columns.Append(myField[columnName], (ADOX.DataTypeEnum)myField["ProviderType"], (int)myField["ColumnSize"]);
}
columnNameList.Add(columnNameValue);
table.Columns.Append(columne);
}
table.Keys.Append((object)priKey, KeyTypeEnum.adKeyPrimary);
}
But when I set the Properties for the columns I got an Exception
internal override void SetColumnProperties(ADOX.Column columne, DbInfo dbInfo)
{
GetColumnProperties(dbInfo);
columne.Properties["Autoincrement"].Value = dbInfo.Field_prop["Autoincrement"];
columne.Properties["Default"].Value = dbInfo.Field_prop["Default"];
columne.Properties["Nullable"].Value = dbInfo.Field_prop["Nullable"];
}
My Program works well for Access DB, but I cannot set it for the DB on SQL Server
Exception (0x80040E21) Multiple-step OLE DB operation generated errors. Check each OLE DB status value, if available. No work was done.
If I try this way
string query = "SELECT * FROM Forms";
DataTable dt = new DataTable();
using (SqlConnection sqlConn = Connection())
using (SqlCommand cmd = new SqlCommand(query, sqlConn))
{
sqlConn.Open();
dt.Load(cmd.ExecuteReader());
}
foreach (DataColumn col in dt.Columns)
{
Console.WriteLine(col.ColumnName);
col.AllowDBNull = true;
dt.AcceptChanges();
col.AutoIncrement = false;
dt.AcceptChanges();
}
it does not change the properties in the DB
The Problem is partially solved
columne.Properties["Autoincrement"].Value = (bool)dbInfo.Autoincrement;
because the dbInfo.Autoincrement was an object I have to write (bool) dbInfo.Autoincrement
Not solved is this
columne.Properties["Default"].Value = (string)dbInfo.Default_Value;
because the type of a value Default_Value can be 0, empty ("") or "-"...I don’t know what i can do in this case

DataAdapter .Update does not update back table

my problem is very common, but I have not found any solution.
This is my code:
public async Task<QueryResult> RollbackQuery(ActionLog action)
{
var inputParameters = JsonConvert.DeserializeObject<Parameter[]>(action.Values);
var data = DeserailizeByteArrayToDataSet(action.RollBackData);
using (var structure = PrepareStructure(action.Query, action.Query.DataBase, inputParameters))
{
//_queryPlanner is the implementor for my interface
return await _queryPlanner.RollbackQuery(structure, data);
}
}
I need to load DataTable (from whereever) and replace data to database. This is my Rollback function. This function use a "CommandStructure" where I've incapsulated all SqlClient objects. PrepareStructure initialize all objects
//_dataLayer is an Helper for create System.Data.SqlClient objects
//ex: _dataLayer.CreateCommand(preSelect) => new SqlCommand(preSelect)
private CommandStructure PrepareStructure(string sql, string preSelect, DataBase db, IEnumerable<Parameter> inputParameters)
{
var parameters = inputParameters as IList<Parameter> ?? inputParameters.ToList();
var structure = new CommandStructure(_logger);
structure.Connection = _dataLayer.ConnectToDatabase(db);
structure.SqlCommand = _dataLayer.CreateCommand(sql);
structure.PreSelectCommand = _dataLayer.CreateCommand(preSelect);
structure.QueryParameters = _dataLayer.CreateParemeters(parameters);
structure.WhereParameters = _dataLayer.CreateParemeters(parameters.Where(p => p.IsWhereClause.HasValue && p.IsWhereClause.Value));
structure.CommandBuilder = _dataLayer.CreateCommandBuilder();
structure.DataAdapter = new SqlDataAdapter();
return structure;
}
So, my function uses SqlCommandBuilder and DataAdapter to operate on Database.
PreSelectCommand is like "Select * from Purchase where CustomerId = #id"
The table Purchase has one primaryKey on ID filed
public virtual async Task<QueryResult> RollbackQuery(CommandStructure cmd, DataTable oldData)
{
await cmd.OpenConnectionAsync();
int record = 0;
using (var cmdPre = cmd.PreSelectCommand as SqlCommand)
using (var dataAdapt = new SqlDataAdapter(cmdPre))
using (var cmdBuilder = new SqlCommandBuilder(dataAdapt))
{
dataAdapt.UpdateCommand = cmdBuilder.GetUpdateCommand();
dataAdapt.DeleteCommand = cmdBuilder.GetDeleteCommand();
dataAdapt.InsertCommand = cmdBuilder.GetInsertCommand();
using (var tbl = new DataTable(oldData.TableName))
{
dataAdapt.Fill(tbl);
dataAdapt.FillSchema(tbl, SchemaType.Source);
tbl.Merge(oldData);
foreach (DataRow row in tbl.Rows)
{
row.SetModified();
}
record = dataAdapt.Update(tbl);
}
}
return new QueryResult
{
RecordAffected = record
};
}
I Execute the code and I don't have any errors, but the data are not updated.
variable "record" contain the right number of modified (??) record, but..... on the table nothing
can someone help me?
EDIT 1:
With SQL Profiler I saw that no query is executed on DB. Only select query on .Fill(tbl) command.
EDIT 2:
Now I have made one change:
tbl.Merge(oldData) => tbl.Merge(oldData, true)
so I see perform the expected query but, with reversed parameters.
UPDATE Purchase SET price=123 where id=6 and price=22
instead of
UPDATE Purchase SET price=22 where id=6 and price=123

Modify an attribute according to its data type c#

For a giving DB, I used CodeSmith to generate a text file that has the following values
(TableName)([TableGUID]) (AttributeName).(AttributeType)
for example
CO_CallSignLists[e3fc5e2d-fe84-492d-ad94-3acced870714] SunSpots.smallint
Now I parsed these values and assigned each to a certain variable
for (int j = 0; j < newLst.Count; j += 2)
{
test_objectName_Guid = newLst[j]; //CO_CallSignLists[e3fc5e2d-fe84-492d-ad94-3acced870714]
test_attr = newLst[j + 1]; //SunSpots.smallint
//Seperate Guid from objectName
string[] obNameGuid = test_objectName_Guid.Split('[',']');
var items = from line in obNameGuid
select new
{
aobjectName = obNameGuid[0],
aGuid = obNameGuid[1]
};
foreach (var item in items)
{
final_objectName = item.aobjectName;
final_oGuid = new Guid(item.aGuid);
}
Console.WriteLine("\nFinal ObjectName\t{0}\nFinal Guid\t\t{1}",
final_objectName, final_oGuid);
string final_attributeName = string.Empty;
string final_attributeType = string.Empty;
string[] words = test_attr.Split('.');
var items2 = from line in words
select new
{
attributeName = words[0],
attributeType = words[1]
};
foreach (var item in items2)
{
final_attributeName = item.attributeName;
final_attributeType = item.attributeType;
}
Console.WriteLine("Attribute Name\t\t{0}\nAttributeType\t\t{1}\n",
final_attributeName, final_attributeType);
I then generate an xml file that loads data from the DB depending on the objectName and its GUID and save this xml in a string variable
string generatedXMLFile = Test.run_Load_StoredProcedure(final_objectName, final_oGuid, Dir);
Now I wanna modify the attribute in this xml file that is equal to the attribute from the parsed txt file. (I wanna modify it according to its type)
public void modifyPassedAttribute(string myFile, string attributeName)
{
Object objString = (Object)attributeName;
string strType = string.Empty;
int intType = 0;
XDocument myDoc = XDocument.Load(myFile);
var attrib = myDoc.Descendants().Attributes().Where(a => a.Name.LocalName.Equals(objString));
foreach (XAttribute elem in attrib)
{
Console.WriteLine("ATTRIBUTE NAME IS {0} and of Type {1}", elem, elem.Value.GetType());
if (elem.Value.GetType().Equals(strType.GetType()))
{
elem.Value += "_change";
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
else if (elem.Value.GetType().Equals(intType.GetType()))
{
elem.Value += 2;
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
}
myDoc.Save(myFile);
}
The problem is that I always says that the value type is 'string' and modifies it as a string (adds "_change").. though when I wanna save the data back into the DB it says you can't assign a nvarchar to a smallint value.
What's wrong with my code? Why do I always get a string type? Is it because all attributes are treated as strings in an xml file? How then can I modify the attribute according to its original type so that I won't get errors when I wanna save it back in the DB?
I'm open for suggestion to optimize the code I know it's not the best code to archive my goal
EDIT
Here is the code to generate the XMLs
public void generate_XML_AllTables(string Dir)
{
SqlDataReader Load_SP_List = null; //SQL reader that gets list of stored procedures in the database
SqlDataReader DataclassId = null; //SQL reader to get the DataclassIds from tables
SqlConnection conn = null;
conn = new SqlConnection("Data Source= EUADEVS06\\SS2008;Initial Catalog=TacOps_4_0_0_4_test;integrated security=SSPI; persist security info=False;Trusted_Connection=Yes");
SqlConnection conn_2 = null;
conn_2 = new SqlConnection("Data Source= EUADEVS06\\SS2008;Initial Catalog=TacOps_4_0_0_4_test;integrated security=SSPI; persist security info=False;Trusted_Connection=Yes");
SqlCommand getDataclassId_FromTables;
int num_SP = 0, num_Tables = 0;
string strDataClass; //Name of table
string sql_str; //SQL command to get
conn.Open();
//Select Stored Procedeurs that call upon Tables in the DB. Tables which have multiple DataClassIds (rows)
//Selecting all Load Stored Procedures of CLNT & Get the table names
// to pass the Load operation which generates the XML docs.
SqlCommand cmd = new SqlCommand("Select * from sys.all_objects where type_desc='SQL_STORED_PROCEDURE' and name like 'CLNT%Load';", conn);
Load_SP_List = cmd.ExecuteReader();
while (Load_SP_List.Read())
{
//Gets the list of Stored Procedures, then modifies it
//to get the table names
strDataClass = Load_SP_List[0].ToString();
strDataClass = strDataClass.Replace("CLNT_", "");
strDataClass = strDataClass.Replace("_Load", "");
sql_str = "select TOP 1 DataclassId from " + strDataClass;
conn_2.Open();
getDataclassId_FromTables = new SqlCommand(sql_str, conn_2);
DataclassId = getDataclassId_FromTables.ExecuteReader();
while (DataclassId.Read())
{
string test = DataclassId[0].ToString();
Guid oRootGuid = new Guid(test);
run_Load_StoredProcedure(strDataClass, oRootGuid, Dir);
num_Tables++;
}
DataclassId.Close();
conn_2.Close();
num_SP++;
}
Load_SP_List.Close();
conn.Close();
System.Console.WriteLine("{0} of Stored Procedures have been executed and {1} of XML Files have been generated successfully..", num_SP,num_Tables);
}
public string run_Load_StoredProcedure(string strDataClass, Guid guidRootId, string Dir)
{
SqlDataReader rdr = null;
SqlConnection conn = null;
conn = new SqlConnection("Data Source= EUADEVS06\\SS2008;Initial Catalog=TacOps_4_0_0_4_test;integrated security=SSPI; persist security info=False;Trusted_Connection=Yes");
conn.Open();
// Procedure call with parameters
SqlCommand cmd = new SqlCommand("CLNT_" + strDataClass + "_Load", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0;
//Adding parameters, in- and output
SqlParameter idParam = new SqlParameter("#DataclassId", SqlDbType.UniqueIdentifier);
idParam.Direction = ParameterDirection.Input;
idParam.Value = guidRootId;
SqlParameter xmlParam = new SqlParameter("#XML", SqlDbType.VarChar, -1 /*MAX*/ );
xmlParam.Direction = ParameterDirection.Output;
cmd.Parameters.Add(idParam);
cmd.Parameters.Add(xmlParam);
rdr = cmd.ExecuteReader(CommandBehavior.SingleResult);
DirectoryInfo dest_2 = new DirectoryInfo(Dir + "\\Copies");
DirectoryInfo dest = new DirectoryInfo(Dir + "\\Backup");
DirectoryInfo source = new DirectoryInfo(Dir);
if (source.Exists == false)
{
source.Create();
if (dest.Exists == false)
{
dest.Create();
}
if (dest_2.Exists == false)
{
dest_2.Create();
}
}
string xmlFile = #Dir + "\\" + strDataClass + " [" + guidRootId + "].xml";
//The value of the output parameter ‘xmlParam’ will be saved in XML format using the StreamWriter.
System.IO.StreamWriter wIn = new System.IO.StreamWriter(xmlFile, false);
wIn.WriteLine(xmlParam.Value.ToString());
wIn.Close();
rdr.Close();
rdr.Close();
conn.Close();
return xmlFile;
}
Short answer:
Is it because all attributes are treated as strings in an xml file?
Yes.
You'll need to store the original type in the Xml - as far as I could tell, you're not including that, so you're discarding the information.
ok so I solved the issue! All I had to do was to pass the attributeType string to the modifyPassedAttribute function and use it to determine the changes I wanna make
Here is the modified final code
public void modifyPassedAttribute(string myFile, string attributeName, string attributeType)
{
Object objString = (Object)attributeName;
string strType = "nvarchar";
string smallintType = "smallint";
string intType = "int";
string dateType = "datetime";
XDocument myDoc = XDocument.Load(myFile);
//var myAttr = from el in myDoc.Root.Elements()
// from attr in el.Attributes()
// where attr.Name.ToString().Equals(attributeName)
// select attr;
var attrib = myDoc.Descendants().Attributes().Where(a => a.Name.LocalName.Equals(objString));
foreach (XAttribute elem in attrib)
{
Console.WriteLine("ATTRIBUTE NAME IS {0} and of Type {1}", elem, elem.Value.GetType());
if (strType.Equals(attributeType))
{
if (elem.Value.EndsWith("_change"))
{
elem.Value = elem.Value.Replace("_change", "");
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
else
{
elem.Value += "_change";
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
}
else if (smallintType.Equals(attributeType))
{
if (elem.Value.EndsWith("2"))
{
elem.Value = elem.Value.Replace("2", "");
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
else
{
elem.Value += 2;
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
}
else if (intType.Equals(attributeType))
{
if (elem.Value.EndsWith("2"))
{
elem.Value = elem.Value.Replace("2", "");
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
else
{
elem.Value += 2;
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
}
else if (dateType.Equals(attributeType))
{
if (elem.Value.EndsWith("2"))
{
elem.Value = elem.Value.Replace("2", "");
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
else
{
elem.Value += 2;
Console.WriteLine("NEW VALUE IS {0}", elem.Value);
}
}
}
myDoc.Save(myFile);
}
the if statements inside are there so that no large numbers would be generated because the 2 is added to the string 100 (i.e. 1002) and if each time I'm gonna add 2 then it's gonna simply crash

Categories

Resources