My listview is being populated by a sql query. The data on sql is an integer "25, 4, 9" etc. But when added to listview its "25.000, 4.000" etc. I've tried using the ("0.#") format but it just tells me it cannot convert to integer. The subitem I'm having the issue with is [VOID_LENGTH]
foreach (Dictionary<string, string> d in resultHistory)
{
ListViewItem lvi = new ListViewItem(d["LOT_NO"]);
lvi.SubItems.Add(d["SERIAL_NO"]);
lvi.SubItems.Add(d["DATE_TIME"]);
lvi.SubItems.Add(d["VOID_LOC"]);
lvi.SubItems.Add(d["VOID_LENGTH"]);
lvi.SubItems.Add(d["EMPL_ID"]);
listView1.Items.Add(lvi);
}
The query
public List<Dictionary<string, string>> GetVoid(string VoidDate, bool orderByDate = false)
{
List<Dictionary<string, string>> results = new List<Dictionary<string, string>>();
string query = "";
List<OleDbParameter> queryParameters = new List<OleDbParameter>();
query = "SELECT LOT_NO, SERIAL_NO, DATE_TIME, VOID_LOC, VOID_LENGTH, EMPL_ID ";
query += "FROM MPCS.BRAZE_VOIDS ";
query += "WHERE TRUNC(DATE_TIME) = TO_DATE(?, 'dd-MON-yy')";
if (orderByDate)
{
query += " order by INS_UPD_TIMESTAMP asc, VOID_LOC desc";
}
queryParameters.Add(new OleDbParameter("DATE_TIME", VoidDate));
results = this.ExecuteParameterQuery(query, queryParameters);
return (results);
}
Your column type in DB is decimal(n,3) I think, you can cast it into int while select. Modify select query part like this
cast(VOID_LENGTH as int) as VOID_LENGTH
Related
I am trying to create an API to insert data from Oracle to PostgreSQL.
So I will query data from Oracle and stored in a DataTable.
Finally generate insert sql and execute in PostgreSQL.
But I found it would occur error if the table contains numeric or timeStamp type field.
Here are my codes.
I will appreciate for any suggestions.
public void Oracle2PG(string fromTable, string toTable)
{
string pgConn = _configuration.GetValue<string>($"ConnectionStrings:PGConnection");
string oraConn = _configuration.GetValue<string>($"ConnectionStrings:OracleConnection");
using (var pgConn = new NpgsqlConnection(sctPgConn))
using (var oraConn = new OracleConnection(sctOraConn))
{
string oraSql = $"select * from {fromTable}";
var dtOra = GetDatatable(oraSql, "", oraConn);
string insertSql = GenerateInsertSql(toTable, dtOra);
pgConn.Execute(insertSql); //occur error "22P02: invalid input syntax for type numeric"
}
}
private static DataTable GetDatatable(string sql, object para, OracleConnection oraConn)
{
var res = oraConn.Query(sql, para);
string json = JsonConvert.SerializeObject(res);
var dtResult = (DataTable)JsonConvert.DeserializeObject(json, (typeof(DataTable)));
return dtResult;
}
private static string GenerateInsertSql(string tableName, DataTable dataTable)
{
var cols = (from DataColumn column in dataTable.Columns select column.ColumnName).ToList();
string colNames = string.Join(", ", cols);
string sql = $"Insert into {tableName} ({colNames}) values";
int cnt = 0;
foreach (DataRow row in dataTable.Rows)
{
cnt += 1;
sql += $"(";
var rowValues = row.ItemArray.Select(s => s.ToString()).ToList();
foreach (string v in rowValues)
{
sql += $"'{v}',";
}
sql = sql.Substring(0, sql.Length - 1);
if (cnt == dataTable.Rows.Count)
{
sql += ") ";
}
else
{
sql += "), ";
}
}
return sql;
}
my call -- I want to pass it a dictionary full of keys and values
QueryBuilder query = new QueryBuilder(new SqliteConnection(#"Data Source = D:/chinook.db"));
Dictionary<string, string> loadDictionary = new Dictionary<string, string>();
Console.WriteLine(query.Create("albums", loadDictionary)); //What do I replace loadDictionary with?
method name
public void Create(string tableName, Dictionary<string, string> columnsAndVals)
{
var commandText = $"insert into {tableName}(";
foreach (var item in columnsAndVals.Keys) // adds keys into command text
{
commandText += item + ",";
}
commandText += ") values(";
foreach (var item in columnsAndVals) // adds values into command text
{
commandText += $"#{item},";
}
var cmd = new SqliteCommand(commandText, Connection);
using (cmd)
{
foreach (var item in columnsAndVals)
{
cmd.Parameters.Add($"#{columnsAndVals.Keys}, #{columnsAndVals}");
}
cmd.ExecuteNonQuery();
}
}
I am constructing a method that will use a sql connection to insert a column and a value into a sql database.
To do this, I am using a dictionary to hold the columns and values I want to insert. (e.g. insert into (tableName)(columnsAndVals.Keys) values (columnsAndVals.Values) etc etc)
What I don't understand is how to establish a dictionary in my driver, then pass it as a parameter into my Create method. Is there a way to do this?
To create an insert query, in addition to the table name, you need to have three lists of values: column name, parameter name, and parameter value. While Dictionary<TKey, TValue allows you to pass only two lists (keys and values).
Therefore, you need to change the method signature. I would completely reject the Dictionary.
You can either pass three separate lists:
public int Create(string tableName, List<string> columnNames, List<string> parameterNames, List<object> parameterValues)
either a single list with a specially created class:
class QueryValue
{
public string ColumnName { get; set; }
public string ParameterName { get; set; }
public object ParameterValue { get; set; }
}
public int Create(string tableName, List<QueryValue> values)
{
var columnNames = string.Join(",", values.Select(v => v.ColumnName));
var parameterNames = string.Join(",", values.Select(v => v.ParameterName));
var sb = new StringBuilder()
.Append("insert into ")
.Append(tableName)
.Append('(')
.Append(columnNames)
.Append(") values(")
.Append(parameterNames)
.Append(')');
var commandText = sb.ToString();
//Console.WriteLine(commandText); // to see result
using (var cmd = new SqliteCommand(commandText, Connection))
{
foreach (var value in values)
{
cmd.Parameters.Add(value.ParameterName, value.ParameterValue);
}
return cmd.ExecuteNonQuery();
}
}
Call the method like this:
var values = new List<QueryValue>
{
new QueryValue{ ColumnName="a", ParameterName="#a", ParameterValue="aa" },
new QueryValue{ ColumnName="b", ParameterName="#b", ParameterValue="bb" },
new QueryValue{ ColumnName="c", ParameterName="#c", ParameterValue="cc" }
};
int rowsAffected = Create("albums", values);
Note that the ExecuteNonQuery method returns the number of rows affected. Therefore, our Create method returns int.
You can also use a tuple instead of a separate class.
However, I strongly oppose such methods. Their use looks rather crooked and fraught with errors.
Each table must have its own insertion method defined, as well as selections, updates, and deletions.
For example
public int InsertUser(int id, string name)
{
var commandText = "insert into User (id, name) values (#id, #name)";
using (var cmd = new SqlCommand(commandText, Connection))
{
cmd.Parameters.Add("id", id);
cmd.Parameters.Add("name", name);
return cmd.ExecuteNonQuery();
}
}
Of course, there will be many such methods, but their use is much easier and less error prone.
We are currently querying the Oracle DB and returning the result in the JSON format.The Query results are returning the more duplicate rows. The Controller is something like below
public HttpResponseMessage Getdetails([FromUri] string[] Column)
{
List<string> selectionStrings = new List<string>();
string connStr = ConfigurationManager.ConnectionStrings["PConnection"].ConnectionString;
using (OracleConnection dbconn = new OracleConnection(connStr))
{
DataSet userDataset = new DataSet();
var colDict = new Dictionary<string, string>()
{
{"CATEGORY", "STCD_PRIO_CATEGORY_DESCR.DESCR"},
{"SESSION_NUMBER", "STCD_PRIO_CATEGORY_DESCR.SESSION_NUM"},
{"SESSION_START_DATE","Trunc(STCD_PRIO_CATEGORY_DESCR.START_DATE)"},
{"SESSION_START_TIME","STCD_PRIO_CATEGORY_DESCR.START_DATE"}}};
foreach (string col in Column)
{
string selector = colDict[col];
selectionStrings.Add(string.Format("{0} AS {1}", selector, col));
}
string selectString = string.Join(",", selectionStrings);
var strQuery = string.Format(#"SELECT {0}
FROM
STCD_PRIO_CATEGORY_DESCR", selectString);
}}}
So if I just add Distinct in the Select statement as
var strQuery = string.Format(#"SELECT DISTINCT {0}
FROM
STCD_PRIO_CATEGORY_DESCR", selectString);
is that should be enough? Or should we be putting DISTINCT before all the Column names
Use distinct or if you are still having trouble you can move the data result into a list and use linq to select only the unique rows.
var result = myList.GroupBy(test => test.id)
.Select(grp => grp.First())
.ToList();
taken from: Select distinct using linq
I want to perform insert into database but in different Tables. Each record i have in my file is assigned with the table Identifiers which will be used as a key. For now what i have done is to make it a generic approach, I have created one more file.txt in which i have specified all the identifiers with the table names. and stored it into a dictionary of string, string.
So, I have example some thing like below in my dictionary:
Table Identifier, Table Name
Table Identifier, Table Name
Then I created another dictionary of string as key (Note: I have used the previous dictionary value as a key into this dictionary) and list of string as values to get the column names of the table name.
So, No I have some thing like this below sample data into my dictionary:
Table Name, Column Names IEnumerable
Table Name, Column Names IEnumerable
Then,
The datafile.txt which contains the data as pipe delimited, I split them and saved into a List of KVP of string and List of String. As I mentioned before, I have table identifiers in my data files. So i used them as key in my KVP and store the split values into List of string.
So, No I have some thing like this below sample data into my List of KVP of string , List of string:
Table Identifier, IEnumerable Values
Table Identifier, IEnumerable Values
Now doing half of the work, I am stuck into my FINAL ISSUE:
Now I have All the identifers , Table Names, Column Names and Values with me into the dictionary and List. And only thing to do is to match and merge the records and DUMP it!
For matching: I have thought to match the List of KVPs key with the dictionarys key and then use the values as a key to get the Column Names.
Expected Scenario Image:
List [[List< Column Names>] , [List of String Values]]
MY CODE:
DataTable dt = null;
SqlConnection cn = null;
SqlDataReader dataReader = null;
SqlBulkCopy bulkInsert = null;
StreamReader reader = null;
string path = string.Empty;
public void test()
{
string TableIdentiferFilepath = HttpContext.Current.Server.MapPath("/testfile/TableIdentifer.txt");
Dictionary<string, string> TableIdentifer_TableName = null;
Dictionary<string, List<string>> Table_Name_ColumnName = null;
using (reader = new StreamReader(TableIdentiferFilepath))
{
TableIdentifer_TableName = new Dictionary<string, string>();
Table_Name_ColumnName = new Dictionary<string, List<string>>();
while (!reader.EndOfStream)
{
string[] curr = reader.ReadLine().Split(new string[] { ",", "\r\n" }, StringSplitOptions.None);
TableIdentifer_TableName.Add(curr[0], curr[1]);
using (cn = new SqlConnection(ConString.Connection.conn))
{
cn.Open();
if (cn.State == ConnectionState.Open)
{
string query = string.Format("select column_name from information_schema.columns where table_name = '{0}' order by ordinal_position", curr[1].ToString());
using (SqlCommand cmd = new SqlCommand(query))
{
using (SqlDataAdapter da = new SqlDataAdapter(query, cn))
{
using (dt = new DataTable())
{
da.Fill(dt);
List<string> dataColumns = dt.AsEnumerable().Select(r => r.Field<string>("column_name")).ToList();
Table_Name_ColumnName.Add(curr[1], dataColumns);
}
}
}
}
}
}
}
string path = HttpContext.Current.Server.MapPath("/TextFile/DataSample.txt");
List<KeyValuePair<string, List<string>>> KVPValues = new List<KeyValuePair<string, List<string>>>();
using (reader = new StreamReader(path))
{
while (!reader.EndOfStream)
{
string[] arr = reader.ReadLine().Split(new string[] { "|", "\r\n" }, StringSplitOptions.None);
var collValues = new List<string>();
KVPValues.Add(new KeyValuePair<string, List<string>>(arr[0], arr.Skip(1).AsEnumerable().ToList()));
foreach (var item in TableIdentifer_TableName)
{
foreach (var item2 in Table_Name_ColumnName.Where(c => c.Key == item.Value))
{
var curr_val = item2.Value;
var currKey = KVPValues.Where(p => p.Key == item.Key).ToList();
}
}
}
}
}
This is a BIG PICTURE! Hopefully now people will understand what i want to achieve.
This is my query
SELECT COUNT(MPRO.OriDes0154) 'QueueCalls' FROM MMProdat.dbo.InstTaWf0154 MPRO WITH(NOLOCK)
WHERE MPRO.Estado0154 = 'QUEUED'
AND F1IdWI02140154<>'VOICEMAIL'
AND F1Camp02930154 = 'Support'
please notice that i have AND F1Camp02930154 = 'Support'
Now I have a list like this:
List<string> compaines = new List<string>();
the values in this list should be in this conidtion AND F1Camp02930154 = 'Support'
for example if the list is empty, i will get an empty result, but if the list has just one value which is Support the query will be
AND F1Camp02930154 = 'Support'
but if the list has two vaules which are Support and Sales then the query will be
AND F1Camp02930154 = 'Support' and `Sales`
how to do that please in c#
where I already have this:
string queryString = "SELECT COUNT(MPRO.OriDes0154) 'QueueCalls' FROM MMProdat.dbo.InstTaWf0154 MPRO WITH(NOLOCK) WHERE MPRO.Estado0154 = 'QUEUED' AND F1IdWI02140154<>'VOICEMAIL'";
Update 1
After # Gordon Linoff comment
I tried this:
List<string> compaines = new List<string>();
string queryString = "SELECT COUNT(MPRO.OriDes0154) 'QueueCalls' FROM MMProdat.dbo.InstTaWf0154 MPRO WITH(NOLOCK) WHERE MPRO.Estado0154 = 'QUEUED' AND F1IdWI02140154<>'VOICEMAIL' AND F1Camp02930154 IN (";
for (int i = 0; i < compaines.Count(); i++) {
queryString += "'" + compaines[i] + "'";
}
queryString += ")";
You can use String.Join() to construct IN () clause, for example :
var companies = new List<string>() { "Support", "Sales" };
string inClause = String.Format(" IN ('{0}')", String.Join("', '", companies));
Console.WriteLine("AND F1Camp02930154" + inClause);
//output :
//AND F1Camp02930154 IN ('Support', 'Sales')