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).
Related
Good day,
In c#, I am trying to run a MySQL update query to update one record, based on its id. Everything goes well as long as I'm not using parameters.
I'm experiencing the issue once I am adding one or several parameters. I have made the test with only one parameter and same problem here.
What am I missing here ?
Thank you very much for your help.
public static void editCustomerTest(ClsCustomerTest pTest)
{
MySqlConnection l_Connection = null;
string l_SpName = string.Empty;
MySqlCommand l_MyCommand = null;
try
{
l_Connection = ClsIconEnv.getDataAccess().MySqlConnection;
ClsDataAccess.OpenConnection(l_Connection);
l_SpName = "update tbTestCustomers " +
"set sName = '#sLastName', " +
"sFirstName = '#sFirstName', " +
"sAddress = '#sAddress' " +
"Where id = #id);";
l_MyCommand = new MySqlCommand(l_SpName, l_Connection);
l_MyCommand.Parameters.Add("#sLastName", pTest.Last_Name);
l_MyCommand.Parameters.Add("#sFirstName", pTest.First_name);
l_MyCommand.Parameters.Add("#sAddress", pTest.Address);
l_MyCommand.Parameters.Add("#id", pTest.id);
l_MyCommand.ExecuteNonQuery(); // <----- This is the line at which the execution stops
ClsDataAccess.CloseConnection(l_Connection);
}
catch (Exception exc)
{
ClsIconErrorManager.manageException(exc);
}
finally
{
}
}
You do not need to wrap your params into the string and you have to use AddWithValue instead of Add if you don't want to explicitly specify the type, like this
l_SpName = "update tbTestCustomers " +
"set sName = #sLastName, " +
"sFirstName = #sFirstName, " +
"sAddress = #sAddress" +
"Where id = #id);";
l_MyCommand.Parameters.AddWithValue("#sLastName", pTest.Last_Name);
l_MyCommand.Parameters.AddWithValue("#sFirstName", pTest.First_name);
l_MyCommand.Parameters.AddWithValue("#sAddress", pTest.Address);
l_MyCommand.Parameters.AddWithValue("#id", pTest.id);
Like this:
l_SpName = #"update tbTestCustomers
set sName = #sLastName,
sFirstName = #sFirstName,
sAddress = #sAddress
Where id = #id";
l_MyCommand = new MySqlCommand(l_SpName, l_Connection);
l_MyCommand.Parameters.AddWithValue("#sLastName", pTest.Last_Name);
l_MyCommand.Parameters.AddWithValue("#sFirstName", pTest.First_name);
l_MyCommand.Parameters.AddWithValue("#sAddress", pTest.Address);
l_MyCommand.Parameters.AddWithValue("#id", pTest.id);
l_MyCommand.ExecuteNonQuery();
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.
I have a c# script task in an SSIS job that calls an API for the purpose of Geocoding. The API is proprietary and works something like this, receives request, takes address string, then attempts to string match to a huge list of addresses (millions) and if it cannot find it, then go out to another service such as google and get geodata info.
As you can imagine this string matching takes up a lot of time per request. Sometimes it's as slow as one request per min, and I have 4M addresses I need to do this for. Getting any dev work on the API side of things is not an option. To give a better picture of the process here is what I'm doing currently:
I pull a list of addresses from database (about 4M) and put it in a datatable and set variables:
// Fill c# datatable with query results
sdagetGeoData.Fill(dtGeoData);
// check to ensure datable has rows
if (dtGeoData.Rows.Count > 0)
{
// if datatable has rows, for every row set the varible
foreach (System.Data.DataRow row in dtGeoData.Rows)
{
localID = row[0].ToString();
address = row[1].ToString();
city = row[2].ToString();
state = row[3].ToString();
zip = row[4].ToString();
country = row[5].ToString();
// after varaibles are set, now run this method to post, get response and insert the string
GetGLFromAddress();
}
}
GetGLFromAddress() works like this:
Take the variables from above and form the JSON. Send the JSON using "POST" and httpWebRequest. Wait for request (time consuming). Return request. Set new variables with the return. Use those variables to update/ insert back into database, THEN loop through the next row in original datatable.
It's important to understand this flow because I need to be able to keep the localID variable with each request so I can update the correct record in the database.
Here is GetGLFromAddress():
private void GetGLFromAddress()
{
// Request JSON data with Payload
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http:");
httpWebRequest.Headers.Add("Authorization", "");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
// this takes the variables from your c# datatable and formats them for json post
var jS = new JavaScriptSerializer();
var newJson = jS.Serialize(new SeriesPost()
{
AddressLine1 = address,
City = city,
StateCode = state,
CountryCode = country,
PostalCode = zip,
CreateSiteIfNotFound = true
});
//// So you can see the JSON thats output
System.Diagnostics.Debug.WriteLine(newJson);
streamWriter.Write(newJson);
streamWriter.Flush();
streamWriter.Close();
}
try
{
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
// javascript serializer... deserializing the returned json so that way you can set the variables used for insert string
var p1 = new JavaScriptSerializer();
// after this line, obj is a fully deserialzed string of json Notice how I reference obj[x].fieldnames below. If you ever want to change the fiels or bring more in
// this is how you do it.
var obj = p1.Deserialize<List<RootObject>>(result);
// you must ensure the values returned are not null before trying to set the variable. You can see when that happens, I'm manually setting the variable value to null.
if (string.IsNullOrWhiteSpace(obj[0].MasterSiteId))
{
retGLMID = "null";
}
else
{
retGLMID = obj[0].MasterSiteId.ToString();
}
if (string.IsNullOrWhiteSpace(obj[0].PrecisionName))
{
retAcc = "null";
}
else
{
retAcc = obj[0].PrecisionName.ToString();
}
if (string.IsNullOrWhiteSpace(obj[0].PrimaryAddress.AddressLine1Combined))
{
retAddress = "null";
}
else
{
retAddress = obj[0].PrimaryAddress.AddressLine1Combined.ToString();
}
if (string.IsNullOrWhiteSpace(obj[0].Latitude))
{
retLat = "null";
}
else
{
retLat = obj[0].Latitude.ToString();
}
if (string.IsNullOrWhiteSpace(obj[0].Longitude))
{
retLong = "null";
}
else
{
retLong = obj[0].Longitude.ToString();
}
retNewRecord = obj[0].IsNewRecord.ToString();
// Build insert string... notice how I use the recently created variables
// string insertStr = retGLMID + ", '" + retAcc + "', '" + retAddress + "', '" + retLat + "', '" + retLong + "', '" + localID;
string insertStr = "insert into table " +
"(ID,GLM_ID,NEW_RECORD_IND,ACCURACY) " +
" VALUES " +
"('" + localID + "', '" + retGLMID + "', '" + retNewRecord + "', '" + retAcc + "')";
string connectionString = "Data Source=; Initial Catalog=; Trusted_Connection=Yes";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand cmd = new SqlCommand(insertStr);
cmd.CommandText = insertStr;
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
connection.Open();
cmd.ExecuteNonQuery();
connection.Close();
}
}
}
{
string insertStr2 = "insert into table " +
"(ID,GLM_ID,NEW_RECORD_IND,ACCURACY) " +
" VALUES " +
"('" + localID + "', null, null, 'Not_Found')";
string connectionString2 = "Data Source=; Initial Catalog=; Trusted_Connection=Yes";
using (SqlConnection connection = new SqlConnection(connectionString2))
{
SqlCommand cmd = new SqlCommand(insertStr2);
cmd.CommandText = insertStr2;
cmd.CommandType = CommandType.Text;
cmd.Connection = connection;
connection.Open();
cmd.ExecuteNonQuery();
connection.Close();
}
}
}
When I have attempted to use Parallel.Foreach, I had issues with the variables. I'd like to have multiple requests ran, but to retain each instance of the variable per request if that makes sense. I have no way to pass the localID to the API and return it, or that would be ideal.
Is this even possible?
And how would I need to structure this call to achieve what I am after?
Essentially I want to be able to send multiple calls, to speed up the entire process.
EDIT: added the code for GetGlFromAddress(). Yes, I am a newb, so please be kind :)
Put all your data in an array and you could call more than one request at a time, it is best to use multi tasks or Async Methods to call API.
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.
So I have been browsing stack overflow and MSDN and cannot find a control (or make sense of the ones I have) to access the data directly of a detailsview. I'm in C# using a .Net WebApplication.
I think what I am looking for is the equivalent in gridview is row.Cells[1].Value can anybody help with the accessor to the DetailsView cells?
What I am trying to do is to access the exact data values I have bound to the DetailsView1
.Text is sufficient for all the numbers and string (only two shown for example) but not for the timestamp MTTS (a datetime) as it lost the milliseconds and the code (SQL query) I use after it cannot find the correct values in the db without the milliseconds. Will I also need to change the way I have bound the data, or some setting to give the bound data millisecond accuracy?
Code example:
Decimal RUN_ID = 0;
DateTime MTTS = new DateTime();
foreach(DetailsViewRow row in DetailsView1.Rows)
{
switch(row.Cells[0].Text)
{
case "RUN_ID":
RUN_ID = Decimal.Parse(row.Cells[1].Text);
break;
case "MTTS":
MTTS = DateTime.Parse(row.Cells[1].ToString());
break;
}
}
I have tried
row.Cells[1].ID = "MTTS";
MTTS = (DateTime)((DataRowView)DetailsView1.DataItem)["MTTS"];
But it does not recognize the MTTS and I am not sure how to set the parameter I have tried a few different things already with no success.
The workaround was messy, essentially I rebuilt the query that gathered the data to the GridView and then I made a function to grab the MTTS directly using LinQ and the parameteres from inside the GridView which assigns the MTTS as a DateTime.
This was in my opinion a bad way of doing things but it worked. I would prefer a better solution.
MTTS = GetMTTS(JOB_PLAN, JOB_NAME,JOB_NAME_ID,RUN_ID,JOB_STATUS);
public DateTime GetMTTS(string JOB_PLAN, string JOB_NAME, string JOB_NAME_ID, Decimal RUN_ID, string JOB_STATUS){
string myEnvName = XXX;
TableName = XXX.ToString();
ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings[myEnvName].ToString();
string thisRUN_ID = RUN_ID.ToString();
cmdText = #"SELECT MTTS FROM " + TableName +
" WHERE JOB_PLAN = '" + JOB_PLAN + "'"
+ " AND JOB_NAME = '" + JOB_NAME + "'"
+ " AND JOB_NAME_ID = '" + JOB_NAME_ID + "'"
+ " AND RUN_ID = '" + thisRUN_ID + "'"
+ " AND JOB_STATUS = '" + JOB_STATUS + "'";
DataSet ds = new DataSet();
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
try
{
SqlCommand SQLcc = new SqlCommand(cmdText,conn);
SqlDataReader reader;
reader = SQLcc.ExecuteReader();
while (reader.Read())
{
MTTS = reader.GetDateTime(0);
}
reader.Dispose();
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
}
return MTTS;
}