How to create a temporary table in MySql from C# datatable? - c#

I am working on a project in which i get some data from a remote server and stores in datatable using C#
DataTable source_db_table;
public void fetch_from_source_db_table(bool verbose, string machine, string table_name, string time_from, string time_to)
{
string query =$"SELECT {table_name}.* " +
$"FROM {table_name} " +
$"WHERE {table_name}" +
$".u_time >='{time_from}' " +
$"AND u_time <= '{time_to}' " +
$"AND mac_id = '{machine}' OR mac_id = 0;";
source_db_table = select_db2(verbose, query);
now I want to use that "datatable" to create a temporary table in MySql . I have searched alot on internet but didnt find anything.

You can do something like this.
StringBuilder sCommand = new StringBuilder("create temporary table tablename(");
foreach (var Col in source_db_table .Columns)
{
sCommand.Append("`"+Col+"`" + " varchar(200), ");
}
sCommand.Append(");");
string scmd = ReplaceLastOccurrence(sCommand.ToString(), ",", "");
in this way your temporary table would be created and now you will just insert rows into this.

Related

Loading data into a designated row in EXCEL

I'm new to C# and with some help on web I have been able to load data from a SQL Server into EXCEL with individual sheets with corresponding data.
I should add that I am trying to accomplish this using a SSIS package "Script Task". C# script.
Now I would like to insert the data in row A7 and not A1. I've tried "insert [9442$A7:A7] (col...) VALUES ... but I get a syntax error. Probably easy solution but I can seem to figure it out.
ERROR: System.Data.OleDb.OleDbException: The Microsoft Access database
engine could not find the object '9442A7:A7'. Make sure the object
exists and that you spell its name and the path name correctly. If
'9442 A7:A7' is not a local object, check your network connection or
contact the server administrator.
Here is my code relevant to creating and loading data into EXCEL.
Thanks in advance.
//Use OLE DB Connection and Create Excel Sheet
Excel_OLE_Con.ConnectionString = connstring;
Excel_OLE_Con.Open();
Excel_OLE_Cmd.Connection = Excel_OLE_Con;
Excel_OLE_Cmd.CommandText = "Create table [" + ColumnValue + "] (" + TableColumns + ")";
Excel_OLE_Cmd.ExecuteNonQuery();
//Write Data to Excel Sheet from DataTable dynamically
foreach (DataTable table in ds.Tables)
{
String sqlCommandInsert = "";
String sqlCommandValue = "";
foreach (DataColumn dataColumn in table.Columns)
{
sqlCommandValue += dataColumn + "],[";
}
sqlCommandValue = "[" + sqlCommandValue.TrimEnd(',');
sqlCommandValue = sqlCommandValue.Remove(sqlCommandValue.Length - 2);
//sqlCommandValue = sqlCommandValue.Replace(",", " ");
sqlCommandInsert = "INSERT into [" + ColumnValue + "A7:A7" + "] (" + sqlCommandValue + ") VALUES(";
int columnCount = table.Columns.Count;
foreach (DataRow row in table.Rows)
{
string columnvalues = "";
for (int i = 0; i < columnCount; i++)
{
int index = table.Rows.IndexOf(row);
columnvalues += "'" + table.Rows[index].ItemArray[i] + "',";
}
columnvalues = columnvalues.TrimEnd(',');
var command = sqlCommandInsert + columnvalues + ")";
//MessageBox.Show(command);
Excel_OLE_Cmd.CommandText = command;
Excel_OLE_Cmd.ExecuteNonQuery();
}
}
Excel_OLE_Con.Close();
Use a Data Flow task for this, not a Script Task. Use a SQL Server data flow component to select your data, and map that result set into an Excel File Output data flow component.
If you want your data to start on A7 (which I assume to mean "the first column but on the seventh row"), I am 99% sure that you can set a property on the Excel File Output component to use 6 rows as "header rows" - this will start your data on the 7th row.

Use a database value to call a variable with the same name

I need to update a table called Calculated in my database, but because I have so many values that I have stored in my system as variables to add/update in the table, I created a separate table in the database called Database Relationships.
This Database Relationships table has a column called Calculated Value which holds all the field names of the Calculated table. The other column, System Field holds all the names of variables that I have created and given values to, which are of all string type and that relate to the corresponding Calculated Value
So by using a FOREACH loop
OleDbDataAdapter relationshipAdapter = new OleDbDataAdapter(relationshipCmd);
DataTable relationshipTable = new DataTable();
relationshipAdapter.Fill(relationshipTable);
string update = "Update [Calculated] SET ";
int i = 0;
int len = relationshipTable.Rows.Count;
foreach (DataRow drr in relationshipTable.Rows)
{
string calc = drr["Calculated Field"].ToString();
var sys = drr["System Field"].ToString();
if (i == len - 1)
{
update += "[" + calc + "] = " + sys + ";";
}
else
{
update += "[" + calc + "] = " + sys + ", ";
}
i++
}
update += "WHERE [NSN] = '" + NSN + "';";
OleDbCommand updateCmd = new OleDbCommand(update);
But this is not working, because after some debugging(?) I did a simple Console.WriteLine(sys) and it would print out the string in the System Field column, instead of the variable with the same name in the system.
I am currently using Microsoft Access as my database platform.
I think having "intermediate" table for temporary storing values in runtime for future saving in another table sounds little bid complicated for me.
If you want to map variables at runtime with column name in the database - use dictionary for example:
Dictionary<string, string> myValues = new Dictionary<string, string>();
Using in the application:
myValues["SomeColumn"] = "your value";
Then saving data to database will be:
var updateCmd = new OleDbCommand();
var query = new StringBuilder();
foreach(KeyValuePair<string, string> value in myValues)
{
string columnName = value.Key;
query.AppendLine($", {columnName} = ?");
var param = new OleDbParameter("#v", value.Value);
// Name of parameter not important, only order
}
if(query.Length > 0)
{
query.Remove(0, 1); // Remove first ',' character
query.Insert("Update [Calculated] SET ");
query.AppendLine("$WHERE [NSN] = '{NSN}';");
}
updateCmd.CommandText = query.ToString();
Very important: you need to use OleDbParameter for passing values to the query.
In you foreach loop, use this:
if (i == len - 1)
{
update += "[" + calc + "] = " + this.GetType().GetProperty(sys).GetValue(this, null)+ ";";
}
else
{
update += "[" + calc + "] = " + this.GetType().GetProperty(sys).GetValue(this, null)+ ", ";
}
The code above assumes that the variables are scoped in the same scope where you are generating your Sql.
In loop , you use the condition:
if (i == len - 1)
but you never change "len" or "i" value in the code.

Loop through a list of words/phrases, match with database table rows

I have a list of words/phrases in a .txt (each word/phrase in new line), I want to loop through each word/phrase and check whether these words/phrases appear in 6th column of the comments table. I cannot work it out the below code, nothing appear in my datagridview despite having the matched "keywords", can anyone review/correct my code? Thank you.
private void button_Search1_Click(object sender, EventArgs e)
{
DataTable flaggedcomments = new DataTable("flaggedcomments");
using (MySqlConnection sqlConn = new MySqlConnection(strProvider))
{
using (MySqlDataAdapter da = new MySqlDataAdapter("SELECT Comment_ID, Comments_Date, Comments_Time, Author, Title, Comments_Comment FROM comments ORDER BY Comments_Date ASC, Comments_Time ASC", sqlConn))
{
da.Fill(flaggedcomments);
}
}
string[] words = File.ReadAllLines(sourceDirTemp + "a_list_of_words_and_phrases.txt");
foreach (DataRow da in flaggedcomments.Rows)
{
string itemComments = da[5].ToString();
if (words.Any(wordOrPhrase => Regex.IsMatch(itemComments, #"\b" + Regex.Escape(wordOrPhrase) + #"\b", RegexOptions.IgnoreCase)))
{
dataGridView_flaggedComments.Rows.Add(da);
string itemTitle = da[4].ToString();
string itemDate = da[1].ToString().Replace(" 12:00:00 AM", "");
string itemTime = da[2].ToString();
string itemAuthor = da[3].ToString();
string itemCommentID = da[0].ToString();
richTextBox_flaggedComments.AppendText("Date: " + itemDate + "\nTime: " + itemTime + "\nCommenter: " + itemAuthor + "\nTitle: " + itemTitle + "\nDescription: " + itemComments + "\nComment ID: " + itemCommentID + "\n\n--------\n\n");
}
}
}
I thought the Rows.Add(da) line would work, but when I clicked the button, it gives me error saying no row can be added to a datagridview control that does not have columns.
Sample "Comments_Comment" is e.g.
Aberdeen Asset Management will release a trading update for the two months to 28 February following regulatory approval for its acquisition of Scottish Widows Investment Partnership.Analysts' expectations: 'For the two months we expect assets under management of £188 billion down 3 per cent from its first quarter.
How about using databinding, instead of trying to add rows to the gridview. You can replace the foreach in your code with this:
var query = flaggedcomments.AsEnumerable().Where(r =>
words.Any(wordOrPhrase => Regex.IsMatch(r.Field<string>("Comments_Comment"), #"\b" + Regex.Escape(wordOrPhrase) + #"\b",
RegexOptions.IgnoreCase)));
dataGridView_flaggedComments.DataSource = query.AsDataView();
You will need to have a reference to System.Data.DataSetExtensions.dll in your visual studio project for this work.

Insert a new record in access using oledb

Can I add a new record into access database which has 15 columns? It's very unconvinient for me to using this sql:
insert into Account(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12,col13,col14,col15) Values(val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11,val12,val13,val14,val15)
There are 2 List consist columns name (name) and values (info). Example:
name[1]="col1";
info[1]="val1";
Is the ordinary of columns name important? Can I use this Sql:
insert into Account(col1) Values(val1)
After that I use an "update" sql and a "for-loop" to set values?
I also get an error:
The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship. Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and try again.
Thank you so much. :)
Do one insert before for loop and update in the for loop.
A sample code is given below.
string Query = "insert into Account(col1) Values(val1)";
// execute it
for(int i=1;i<name.count -1;i++)
{
Query = "Update Account set " + name[i] + " = " + info[i] + " where col1 = val1";
// execute
}
Code not tested.
public static void insert(String[] name ,String[] info)
{
String Names = "";
String Cols = "";
for(int i=0;i < name.Length;i++)
{
Names += (Names == "" ? "" : ", ") + name[i];
Cols += (Cols == "" ? "" : ", ") + "'" + info[i] + "'";
}
String Query = "insert into Account (" + Names + ") Values (" + Cols + ")";
Console.WriteLine(Query);
}
Code not tested and note that I added single quotes for values assuming that all values are string type.

Writing Server stored procedures in c#

I am new to c# and am having a difficult time figuring this out,
public UserNotificationFeed GetNotificationFeed(TenantInfo tenant, List<int> notificationId)
{
UserNotificationFeed userNotificationFeed = new UserNotificationFeed();
string sql = "select " + NotificationFieldList + " from UserNotificationFeed where MsgId = #MsgId";
Database databaseObj = SocialDB.GetDataBase(tenant.ConnectionString, tenant.ProviderName);
DbCommand commandObj = databaseObj.GetSqlStringCommand(sql);
databaseObj.AddInParameter(commandObj, "MsgId", DbType.Int64, notificationId );
using (IDataReader reader = databaseObj.ExecuteReader(commandObj))
{
while (reader.Read())
{
userNotificationFeed = new UserNotificationFeed();
this.PopulateObject(userNotificationFeed, reader);
}
}
return userNotificationFeed;
}
What I want is that the
string sql = "select " + NotificationFieldList + " from UserNotificationFeed where MsgId = #MsgId";
to take a list of MsgIds passed on by a List<int> notificationId.
Any help is really appreciated .
A simple approach, since the data is int (and therefore injection safe) would be to just use:
string sql = "select " + NotificationFieldList +
" from UserNotificationFeed where MsgId in (" +
string.Join(",", notificationId) + ")";
(and don't add the parameter)
If you want it to be fully parameterized, that is possible too, but harder (it requires a flexible number of parameters). There are tools that can help, though. For example, with dapper that would be:
var rows = connection.Query("select " + NotificationFieldList +
" from UserNotificationFeed where MsgId in #MsgId",
new {MsgId = notificationId}).ToList();
here dapper will automatically tweak the SQL and add the correct number of parameters. But: dapper won't work directly with your IDataReader-based PopulateObject method (since it has already populated some objects).

Categories