I need to do this in my codes;
Get data from 2 columns in a database (laborer and trx_date)
Place the extracted data to a DataTable
Explode the first column in the DataTable
Place exploded_laborer and trx_date to an array with
key->exploded_laborer
exploded=>trx_date
I am able to get to number 3 I just need to do number 4. My code is below:
private void GetLocalData()
{
const string sql = #"SELECT laborer, trx_date from tbl_jobs WHERE trx_date BETWEEN #fromDate AND #toDate";
var laborerDataTable = new DataTable();
using (var conn = new SqliteAccess().ConnectToSqlite())
{
using (var cmd = new SQLiteCommand(sql, conn))
{
conn.Open();
cmd.Parameters.AddWithValue("#fromDate", dtpFrom.Value.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("#toDate", dtpTo.Value.ToString("yyyy-MM-dd"));
laborerDataTable.Load(cmd.ExecuteReader());
}
}
var exploded = new List<string>();
foreach (DataRow row in laborerDataTable.Rows)
{
exploded.Add(row["laborer"].ToString().Split('|')[0]);
}
}
Your help is very much appreciated.
I think you are supposed to create Dictionary<TKey,TValue> which represents a collection of keys and values. This might do the trick for you
laborerDataTable.AsEnumerable()
.Select(row => laborerDataTable.Columns.Cast<DataColumn>()
.ToDictionary(column => row[laborer] as string
column => row[trx_date] as string))
Thus the complete code might look like
private void GetLocalData()
{
const string sql = #"SELECT laborer, trx_date from tbl_jobs WHERE trx_date BETWEEN #fromDate AND #toDate";
var laborerDataTable = new DataTable();
using (var conn = new SqliteAccess().ConnectToSqlite())
{
using (var cmd = new SQLiteCommand(sql, conn))
{
conn.Open();
cmd.Parameters.AddWithValue("#fromDate", dtpFrom.Value.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("#toDate", dtpTo.Value.ToString("yyyy-MM-dd"));
laborerDataTable.Load(cmd.ExecuteReader());
}
}
var LabDict = laborerDataTable.AsEnumerable()
.Select(row => laborerDataTable.Columns.Cast<DataColumn>()
.ToDictionary(column => row[laborer] as string
column => row[trx_date] as string))
}
Edit
This is just to create a dummy table.
static DataTable GetTable()
{
// Here we create a DataTable with four columns.
DataTable table = new DataTable();
table.Columns.Add("laborer", typeof(string));
table.Columns.Add("trx_date", typeof(string));
// Here we add five DataRows.
table.Rows.Add("Indocin", "12/12/2010");
table.Rows.Add("Enebrel", "12/1/2011");
table.Rows.Add("Hydralazine", "1/12/2012");
table.Rows.Add("Combivent", "11/12/2013");
table.Rows.Add("Dilantin", "12/11/2014");
return table;
}
normal core C# way
DataTable laborerDataTable = GetTable();
Dictionary<string, string> exploded = new Dictionary<string, string>();
foreach(DataRow row in laborerDataTable.Rows)
{
exploded.Add(row.Field<string>(0), row.Field<string>(1));
}
Also, how do I print each of the row to a console?
foreach(var dct in exploded)
{
Console.WriteLine(dct.Key + " Date is " + dct.Value);
}
If you are expecting the result to a Key-Value pair then why an array? why not a Dictionary<string, string>? You can try something like this :
Dictionary<string, string> laborerDict = laborerDataTable.AsEnumerable()
.ToDictionary(x => x.Field<string>("laborer"),
x => x.Field<string>("trx_date"));
Use in built HashMap in java refer the code below
HashMap map = new HashMap<>();
Map.put(key,value);
And to get data from map use
Map.get(key)
It has a lot of function, maybe you can refer them by searching Java API
when you want to have Key=>Value better you use Dictionary instead of List
var exploded = new Dictionary<string,string>();
foreach (DataRow row in laborerDataTable.Rows)
{
exploded.Add(row["laborer"].ToString(),(row["trx_date"].ToString());
}
Related
I have a DataTable that returns me data as follows:
APP | VERSION
____|________
app1| 1.0
app1| 2.0
app1| 3.0
app2| 1.0
app3|
As you see, "app1" has multiple versions, and some apps don't have any versions. I need to store this Datatable result in some sort of List for later usage in my code, so I came up with Dictionary, but can't get It to work. Here is what I tried:
public static Dictionary<string, List<string>> AppVer()
{
string SQL = "SELECT column1, column2 FROM myTable a LEFT JOIN
myTable2 v ON v.ID_FK=a.ID_PK";
Dictionary<string, List<string>> versions = new Dictionary<string,
List<string>>();
DataTable dt = new DataTable();
try
{
using (var conn = new OracleConnection(conn_string))
{
conn.Open();
using (OracleCommand cmd = new OracleCommand(SQL, conn))
{
using (OracleDataAdapter dad = new OracleDataAdapter(cmd))
{
dad.Fill(dt);
}
versions = dt.AsEnumerable().ToDictionary<DataRow, string, List<string>>(row => row[0].ToString(), new List<string>(row=> row[1].ToString()));
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return versions;
}
However, I get error
"Cannot convert lambda expression to type 'string' because it is not a
delegate type".
How could I store my DataTable to dictionary ?
EDIT:
Dictionary<string, List<Version>> all_versions = AppVer();
StringBuilder sb = new StringBuilder();
foreach (var item in all_versions)
{
sb.AppendFormat("{0} - {1}{2}", item.Key, item.Value, Environment.NewLine);
}
string result = sb.ToString().TrimEnd();
MessageBox.Show(result);
ILookup<string, string> myLookup = dt.AsEnumerable().ToLookup(row => row[0].ToString(), row => row[1].ToString());
IEnumerable<string> myValues = myLookup["app1"];
// Loop through lookup.
foreach(var group in myLookup)
{
string key = group.Key;
IEnumerable<string> myValues = group;
Console.WriteLine("Group {0} has {1} elements", key, myValues);
}
You need to GroupBy by the key, then you can use ToList on the groups. You know that there's a Version-class which you could use? So i'd prefer a Dictionary<string, List<Version>>:
public static Dictionary<string, List<Version>> AppVer()
{
Dictionary<string, List<Version>> versions = null;
string SQL = "SELECT column1, column2 FROM myTable a LEFT JOIN myTable2 v ON v.ID_FK = a.ID_PK";
var dt = new DataTable();
try
{
using (var conn = new OracleConnection(conn_string))
using (var da = new OracleDataAdapter(SQL, conn))
{
da.Fill(dt);
}
versions = dt.AsEnumerable()
.GroupBy(r => r.Field<string>(0))
.ToDictionary(
g => g.Key,
g => g.Select(r => Version.Parse(r.Field<string>(1))).ToList());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return versions;
}
One of the benefits of the Version class it that it sorts correctly, so 10.1 after 2.1.
can someone tells me how to do this?
I have this function in c#:
public string ConvertLocationTableToString()
{
int radius = 0;
string locationType = "marker";
DataTable dt = new DataTable();
Using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString()))
{
Using (SqlCommand cmd = new SqlCommand("SELECT lat=Latitude, lng=Longitude, FROM Locations", con))
{
con.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
Dictionary<string, object> row;
foreach (DataRow dr in dt.Rows)
{
row = new Dictionary<string, object>();
foreach (DataColumn col in dt.Columns)
{
row.Add(col.ColumnName, dr[col]);
}
rows.Add(row);
}
return serializer.Serialize(rows);
}
}
}
The table Locations contains two rows with latitude and lontitude values.
It produces string value of:
[{"lat":24.816925048828125,"lng":-107.37641906738281}
, {"lat":24.815664291381836,"lng":-107.38169097900391}]
.
But I want to produce the following:
[{"Coordinates": [{"lat":24.816925048828125,"lng":-107.37641906738281}], "Radius": 0,"LocationType": "marker"}
,{ "Coordinates": [{lat":24.815664291381836,"lng":-107.38169097900391}],"Radius": 0,"LocationType": "marker"}}]
Please notice that ‘Radius’ and ‘LocationType’ are not fields in the table.
Thank you for your help.
rubenc
You are serializing rows, which is returned from the table. If you created an object in C# that matches your desired output, then looped over the rows returned and set the relevant items, you could then serialize that.
In your case, the object would consist of:
- Coordinates - some type of list
- Radius - int I assume
- LocationType - guessing enum
Then you would create an arrray of these, and serialize the array.
Hello everyone I'm trying to write code that can get select table information with (string)tableName, but i get error when i try to put value to Dictionary.
P.S : I have generated EF DB model.
public Dictionary<string, List<object>> GetTableInformation(string tableName, FinkonaDatabaseType type)
{
Dictionary<string, List<object>> _returnableDictionary = new Dictionary<string, List<object>>();
PropertyInfo prop = optimumEntities.GetType().GetProperty(tableName);
Type tableType = prop.PropertyType.GenericTypeArguments[0];
var items = optimumEntities.Database.SqlQuery(tableType, "SELECT * FROM " + tableName);
foreach (var item in items)
{
foreach (PropertyInfo info in item.GetType().GetProperties())
{
if (!_returnableDictionary.ContainsKey(info.Name))
{
_returnableDictionary.Add(info.Name, new List<object>());
}
_returnableDictionary[info.Name].Add(info.GetValue(info, null));
// System.Reflection.TargetException, Object does not match target type.
}
}
return _returnableDictionary;
}
Using ADO.NET DataTables will be easier here, as EF is used for strongly typing data. Since you are not too worried about the data types coming back, a DataTable will be easier to navigate.
Here is an examples of this:
public Dictionary<string, List<object>> GetTableInformation(string tableName, FinkonaDatabaseType type)
{
var sqlText = "SELECT * from " + tableName;
DataTable dt = new DataTable();
// Use DataTables to extract the whole table in one hit
using(SqlDataAdapter da = new SqlDataAdapter(sqlText, optimumEntities.Database.ConnectionString)
{
da.Fill(dt);
}
var tableData = new Dictionary<string, List<object>>();
// Go through all columns, retrieving their names and populating the rows
foreach(DataColumn dc in dt.Columns)
{
string columnName = dc.Name;
rowData = new List<object>();
tableData.Add(columnName, rowData);
foreach(DataRow dr in dt.Rows)
{
rowData.Add(dr[columnName]);
}
}
return tableData;
}
I want to store the result of select query in an array in C#. Please tell me how to get datatable values and store in an array. My select query result contains n rows and only one column.
Replace type with the data type of your single column (e.g. int, string, ...) and myField with the name of your single column.
var myArray = (from row in myDataTable.AsEnumerable()
select row.Field<type>("myField")).ToArray();
Using the magic of C#'s generics and type inference, your array will automatically have the correct data type (e.g. int[], string[], ...).
Try something like this
private void getData()
{
SqlCeConnection conn = new SqlCeConnection("data source='c:\\northwind.sdf'; mode=Exclusive;");
SqlCeDataAdapter da = new SqlCeDataAdapter("Select [Unit Price] from Products", conn);
DataTable dtSource = new DataTable();
da.Fill(dtSource);
DataRow[] dr = new DataRow[dtSource.Rows.Count];
dtSource.Rows.CopyTo(dr, 0);
double[] dblPrice= Array.ConvertAll(dr, new Converter<DataRow , Double>(DataRowToDouble));
}
public static double DataRowToDouble(DataRow dr)
{
return Convert.ToDouble(dr["Unit Price"].ToString());
}
DataTable mydt = new DataTable();
ArrayList aLrows = new ArrayList();
foreach (DataRow dataRow in mydt.Rows)
{
aLrows.Add(string.Join(";", dataRow.ItemArray.Select(item => item.ToString)));
}
After connecting to the database, can I get the name of all the columns that were returned in my SqlDataReader?
var reader = cmd.ExecuteReader();
var columns = new List<string>();
for(int i=0;i<reader.FieldCount;i++)
{
columns.Add(reader.GetName(i));
}
or
var columns = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList();
There is a GetName function on the SqlDataReader which accepts the column index and returns the name of the column.
Conversely, there is a GetOrdinal which takes in a column name and returns the column index.
You can get the column names from a DataReader.
Here is the important part:
for (int col = 0; col < SqlReader.FieldCount; col++)
{
Console.Write(SqlReader.GetName(col).ToString()); // Gets the column name
Console.Write(SqlReader.GetFieldType(col).ToString()); // Gets the column type
Console.Write(SqlReader.GetDataTypeName(col).ToString()); // Gets the column database type
}
Already mentioned. Just a LINQ answer:
var columns = reader.GetSchemaTable().Rows
.Cast<DataRow>()
.Select(r => (string)r["ColumnName"])
.ToList();
//Or
var columns = Enumerable.Range(0, reader.FieldCount)
.Select(reader.GetName)
.ToList();
The second one is cleaner and much faster. Even if you cache GetSchemaTable in the first approach, the querying is going to be very slow.
If you want the column names only, you can do:
List<string> columns = new List<string>();
using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly))
{
DataTable dt = reader.GetSchemaTable();
foreach (DataRow row in dt.Rows)
{
columns.Add(row.Field<String>("ColumnName"));
}
}
But if you only need one row, I like my AdoHelper addition. This addition is great if you have a single line query and you don't want to deal with data table in you code. It's returning a case insensitive dictionary of column names and values.
public static Dictionary<string, string> ExecuteCaseInsensitiveDictionary(string query, string connectionString, Dictionary<string, string> queryParams = null)
{
Dictionary<string, string> CaseInsensitiveDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
try
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = query;
// Add the parameters for the SelectCommand.
if (queryParams != null)
foreach (var param in queryParams)
cmd.Parameters.AddWithValue(param.Key, param.Value);
using (SqlDataReader reader = cmd.ExecuteReader())
{
DataTable dt = new DataTable();
dt.Load(reader);
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn column in dt.Columns)
{
CaseInsensitiveDictionary.Add(column.ColumnName, row[column].ToString());
}
}
}
}
conn.Close();
}
}
catch (Exception ex)
{
throw ex;
}
return CaseInsensitiveDictionary;
}
Use an extension method:
public static List<string> ColumnList(this IDataReader dataReader)
{
var columns = new List<string>();
for (int i = 0; i < dataReader.FieldCount; i++)
{
columns.Add(dataReader.GetName(i));
}
return columns;
}
For me, I would write an extension method like this:
public static string[] GetFieldNames(this SqlDataReader reader)
{
return Enumerable.Range(0, reader.FieldCount).Select(x => reader.GetName(x)).ToArray();
}
I use the GetSchemaTable method, which is exposed via the IDataReader interface.
You sure can.
protected void GetColumNames_DataReader()
{
System.Data.SqlClient.SqlConnection SqlCon = new System.Data.SqlClient.SqlConnection("server=localhost;database=northwind;trusted_connection=true");
System.Data.SqlClient.SqlCommand SqlCmd = new System.Data.SqlClient.SqlCommand("SELECT * FROM Products", SqlCon);
SqlCon.Open();
System.Data.SqlClient.SqlDataReader SqlReader = SqlCmd.ExecuteReader();
System.Int32 _columncount = SqlReader.FieldCount;
System.Web.HttpContext.Current.Response.Write("SqlDataReader Columns");
System.Web.HttpContext.Current.Response.Write(" ");
for ( System.Int32 iCol = 0; iCol < _columncount; iCol ++ )
{
System.Web.HttpContext.Current.Response.Write("Column " + iCol.ToString() + ": ");
System.Web.HttpContext.Current.Response.Write(SqlReader.GetName( iCol ).ToString());
System.Web.HttpContext.Current.Response.Write(" ");
}
}
This is originally from: http://www.dotnetjunkies.ddj.com/Article/B82A22D1-8437-4C7A-B6AA-C6C9BE9DB8A6.dcik
It is easier to achieve it in SQL
var columnsList = dbContext.Database.SqlQuery<string>("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'SCHEMA_OF_YOUE_TABLE' AND TABLE_NAME = 'YOUR_TABLE_NAME'").ToList();