private String[] GetProperties(EContent_EcontentFields eContentField)
{
List<String> list = new List<String>();
Type fieldType = eContentField.GetType();
var properties = fieldType.GetProperties();
foreach (var prop in properties)
{
if (prop.MemberType == MemberTypes.Property)
{
if (prop.PropertyType.IsGenericType)
{
dynamic items = prop.GetValue(eContentField, null);
foreach (var item in items)
{
Type typeItem = item.GetType();
list.Add(item);
}
}
}
}
return list.ToArray();
}
This is my method to retrieve an array of strings with the properties of my entity but the statement:
if (prop.PropertyType.IsGenericType)
It's always false.
I've copy-pasted the code so maybe I'm missing something. Something that I can't see.
var result = new List<string>();
var type = eContentField.GetType();
foreach (var prop in type.GetProperties())
{
result.Add(prop.Name);
}
return result.ToArray();
}
This is about twice faster than your method, if you are interested in speed.
Ps: if you change the foreach into a for loop, it wil be a bit faster, but not a lot :)
I found a solution to retrieve all the property names.
private String[] GetProperties(EContent_EcontentFields eContentField)
{
List<String> list = new List<String>();
Type type = eContentField.GetType();
var properties = type.GetProperties().Where(x => x.MemberType == MemberTypes.Property).Select(x => x.Name);
foreach (var item in properties)
{
if(item != null)
list.Add(item.ToString());
}
return list.ToArray();
}
Related
The entity instance here is getting a list of 10 arrays from which I need to get the value of invalid Dir.
var entityInstance = FacadeServiceContext.LoadEntityBaseInstances(entityName, searchParams, context: null).ToList();
if (entityInstance != null && entityInstance.Any())
{
var invalidDirflag = entityInstance.Where(item => item.Equals(CustomConstants.ICMInvalidDIR));
foreach (var item in entityInstance )
{
if( invalidDirflag.Equals(false))
{
var filters = new Dictionary<string, List<string>>();
addHeaderFilters(filters, request);
addLineItems(filters, (JArray)request[SourcingConstants.ClientSoCoApplicableDocumentsAttributesItemsFieldName]);
coAppDocs.AddRange(filterDeterminedDocuments(entityInstance, filters));
}
}
}
I get an exception with the above code:
Enumeration yielded no results
How do I do this?
Linq Function "Where" could return empty iteration.
Check your code line 4. Plus, "Where" Function does not return bool type.
I recommend to use "FirstOrDefault()" on line 4. If iteration is empty, variable invalidDirflag will be set to false.
See below code.
var entityInstance = FacadeServiceContext.LoadEntityBaseInstances(entityName, searchParams, context: null).ToList();
if (entityInstance != null && entityInstance.Any())
{
var invalidDirflag = entityInstance.Where(item => item.Equals(CustomConstants.ICMInvalidDIR)).FirstOrDefault();
foreach (var item in entityInstance )
{
if( invalidDirflag.Equals(false))
{
var filters = new Dictionary<string, List<string>>();
addHeaderFilters(filters, request);
addLineItems(filters, (JArray)request[SourcingConstants.ClientSoCoApplicableDocumentsAttributesItemsFieldName]);
coAppDocs.AddRange(filterDeterminedDocuments(entityInstance, filters));
}
}
}
I got a result of a query in nHibernate:
var result = _Session.CreateSQLQuery("SELECT 'just a string' as Type, NAME FROM SCHEMA.PERSON where NAME like ('%A%')").List();
and I want to show this result in a DataGridView. So I tried:
this.results.DataSource = result;
But this does not to work (It shows just a lot of stuff like "Length", "Long Length", "Rank" and so aon but not the actual sql result) as result is of type: System.Collections.IList System.Collections.Generic.List and in fact seems like a object array inside a object array.
So I tried:
this.results.DataSource = from res in result.Cast<List<object[]>>()
select new
{
T = res[0][0],
V = res[0][1]
};
but this only shows an empty control.
So how to show the results and as an advanced task how to show the alias/select result names as Column Headers?
btw. This should work for every SQL. So I cant use mappingFiles.
After a lot of search and help from this question: NHibernate output columns/projections of CreateQuery().list()
I found a solution that works for me:
var query = _Session.CreateSQLQuery("SELECT 'just a string' as Type, NAME FROM SCHEMA.PERSON where NAME like ('%A%')").SetResultTransformer(Transformers.AliasToEntityMap);
var result = query.List();
var tab = new DataTable();
if (result.Count > 0)
{
var asHash = result[0] as Hashtable;
foreach (DictionaryEntry item in asHash)
{
tab.Columns.Add(item.Key as string);
}
foreach (Hashtable item in result)
{
var newobj = new Object[tab.Columns.Count];
int i = 0;
foreach (DictionaryEntry row in item)
{
newobj[i]= row.Value;
i++;
}
tab.Rows.Add(newobj);
}
}
this.results.DataSource = tab;
Im sure that there are other (better) ways to do it, but hey: It works.
The other solutions do not preserve the projection order. I implemented this (ugly) data transformer to keep the order:
Usage example:
var command = "SELECT 'just a string' as Type, NAME FROM SCHEMA.PERSON where NAME like ('%A%')";
var query = _Session.CreateSQLQuery(command)
.SetResultTransformer(new DataTableTransformer());
var dataTable = (DataTable)query.List()[0];
Implementation:
public class DataTableTransformer : IResultTransformer
{
bool _isHeaderRowAdded;
public object TransformTuple(object[] tuple, string[] aliases)
{
if (false == _isHeaderRowAdded)
{
_isHeaderRowAdded = true;
return new Tuple<string[], object[]>(aliases, tuple);
}
return tuple;
}
public IList TransformList(IList collection)
{
if (collection.Count == 0)
{
return new []{new DataTable()};
}
var dataTable = new DataTable();
var headerAndFirstRow = (Tuple<string[], object[]>)collection[0];
foreach (var columnName in headerAndFirstRow.Item1)
{
dataTable.Columns.Add(columnName);
}
var newRow = dataTable.NewRow();
newRow.ItemArray = headerAndFirstRow.Item2;
dataTable.Rows.Add(newRow);
int index = 0;
foreach (var item in collection)
{
if (index++ == 0) continue;
var dataRow = dataTable.NewRow();
dataRow.ItemArray = (object[])item;
dataTable.Rows.Add(dataRow);
}
return new []{dataTable};
}
}
I am pulling some data from a BigQuery table using the code below in C#
BigQueryClient client = BigQueryClient.Create("<Project Name>");
BigQueryTable table = client.GetTable("<Database>", "Students");
string sql = $"select * FROM {table} where Marks='50'";
BigQueryResults results = client.ExecuteQuery(sql);
foreach (BigQueryRow row in results.GetRows())
{
}
I want to be able to either read the entire results variable into JSON or be able to get the JSON out of each row.
Of course, I could create a class that models the table. And inside the foreach loop, I could just read each row into the class object. The class object I can try to serialize into JSON using a third party like "newton soft".
Something like :
class Student{
int id; // assume these are columns in the db
string name;
}
My foreach would now look like:
foreach (BigQueryRow row in results.GetRows())
{
Student s=new Student();
s.id = Convert.ToString(row["id"]);
s.name= Convert.ToString(row["name"]);
// something like string x=x+ s.toJSON(); //using newton soft
}
This way string x will have the JSON generated and appended for each row.
Or is there a way I can just add each student to a collection or List and then get the JSON from the whole list?
This whole reading row by row and field by field seems tedious to me and there must be a simpler way I feel. Did not see any support from Google BigQuery for C# to directly convert to JSON. They did have something in Python.
If not then the list to JSON would be better but I am not sure if it supported.
Update :
https://github.com/GoogleCloudPlatform/google-cloud-dotnet/blob/master/apis/Google.Cloud.BigQuery.V2/Google.Cloud.BigQuery.V2/BigQueryRow.cs
Looks like the Big Query Row class has a RawRow field which is of Type TableRow. And the class uses JSON references so , I am sure they have the data of the row in JSON format . How can I expose it to me ?
This might be a little late but you can use:
var latestResult = _bigQueryClient.ExecuteQuery($"SELECT TO_JSON_STRING(t) FROM `{ProjectId}.{DatasetId}.{TableName}` as t", null
All columns will be serialized as json and placed in the first column on each row. You can then use something like Newtonsoft to parse each row easily.
I ran into the same issue.
I am posting this solution which is not optimized for performance but very simple for multiple data types.
This allows you to deserialize anything (almost)
public class BQ
{
private string projectId = "YOUR_PROJECT_ID";
public BQ()
{
}
public List<T> Execute<T>(string sql)
{
var client = BigQueryClient.Create(projectId);
List<T> result = new List<T>();
try
{
string query = sql;
BigQueryResults results = client.ExecuteQuery(query, parameters: null);
List<string> fields = new List<string>();
foreach (var col in results.Schema.Fields)
{
fields.Add(col.Name);
}
Dictionary<string, object> rowoDict;
foreach (var row in results)
{
rowoDict = new Dictionary<string, object>();
foreach (var col in fields)
{
rowoDict.Add(col, row[col]);
}
string json = Newtonsoft.Json.JsonConvert.SerializeObject(rowoDict);
T o = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(json);
result.Add(o);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
client.Dispose();
Console.WriteLine("Done.");
}
return result;
}
}
You can use Newtonsoft.Json. First download by PackageManager Console the Nuget Package, here you can get the command to do that.
After download you can use it as the following code:
List<Student> list = new List<Student>();
foreach (BigQueryRow row in results.GetRows())
{
Student s=new Student();
s.id = Convert.ToString(row["id"]);
s.name= Convert.ToString(row["name"]);
list.Add(s);
}
var jsonResult = Newtonsoft.Json.JsonConvert.SerializeObject(list);
I hope this can help you.
Here is the complete solution for casting BigQueryResults or GetQueryResultsResponse or QueryResponse data to Model/JSON format using C# reflection:
public List<T> GetBQAsModel<T>(string query) where T : class, new()
{
var bqClient = GetBigqueryClient();
var res = bqClient.ExecuteQuery(query, parameters: null);
return GetModels<T>(res);
}
private List<T> GetModels<T>(BigQueryResults tableRows) where T : class, new()
{
var lst = new List<T>();
foreach (var item in tableRows)
{
var lstColumns = new T().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
var newObject = new T();
for (var i = 0; i < item.RawRow.F.Count; i++)
{
var name = item.Schema.Fields[i].Name;
PropertyInfo prop = lstColumns.FirstOrDefault(a => a.Name.ToLower().Equals(name.ToLower()));
if (prop == null)
{
continue;
}
var val = item.RawRow.F[i].V;
prop.SetValue(newObject, Convert.ChangeType(val, prop.PropertyType), null);
}
lst.Add(newObject);
}
return lst;
}
private List<T> GetModels<T>(GetQueryResultsResponse getQueryResultsResponse) where T : class, new()
{
var lst = new List<T>();
foreach (var item in getQueryResultsResponse.Rows)
{
var lstColumns = new T().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
var newObject = new T();
for (var i = 0; i < item.F.Count; i++)
{
var name = getQueryResultsResponse.Schema.Fields[i].Name;
PropertyInfo prop = lstColumns.FirstOrDefault(a => a.Name.ToLower().Equals(name.ToLower()));
if (prop == null)
{
continue;
}
var val = item.F[i].V;
prop.SetValue(newObject, Convert.ChangeType(val, prop.PropertyType), null);
}
lst.Add(newObject);
}
return lst;
}
private List<T> GetModels<T>(QueryResponse queryResponse) where T : class, new()
{
var lst = new List<T>();
foreach (var item in queryResponse.Rows)
{
var lstColumns = new T().GetType().GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
var newObject = new T();
for (var i = 0; i < item.F.Count; i++)
{
var name = queryResponse.Schema.Fields[i].Name;
PropertyInfo prop = lstColumns.FirstOrDefault(a => a.Name.ToLower().Equals(name.ToLower()));
if (prop == null)
{
continue;
}
var val = item.F[i].V;
prop.SetValue(newObject, Convert.ChangeType(val, prop.PropertyType), null);
}
lst.Add(newObject);
}
return lst;
}
I would do something like this:
var res = Result. Getrows. Select(x=> new student(){id=x[`ID']}).
And then:
var js = json. Conver(res);
This way is much faster and clearer.
I code below that works well with an API for the DataTables plugin; for each column that the DataTables searches in, regardless of type, the filter works as expected based on what is supplied.
DataTables also has a "Global" search feature where you can search in one field and if there is a match in ANY of the rows for said data then a match is returned.
What I am Hoping For:
A way to perform a search on an IEnumerable such that if any of the fields match the search the result is returned.
NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
var generalSearch = nvc["sSearch"];
if (!string.IsNullOrWhiteSpace(generalSearch))
{
var generalSearchProperties = typeof(T).GetProperties();
foreach (var currentProperty in generalSearchProperties)
{
Type propType = currentProperty.PropertyType;
set = set.Where(StaticUtility.PropertyEquals<T>(currentProperty, generalSearch, propType));
/* ^^^^^ */
/*
Instead of the "Where" here I am looking for something like "where or" which can be added to the IEnumerable.
*/
}
}
Original Code:
protected virtual IQueryable<T> FilterEntitiesBySearchParameters(IQueryable<T> set)
{
try
{
NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
var props = typeof(T).GetProperties();
foreach (var prop in props)
{
var name = prop.Name;
var val = nvc[name];
Type propType = prop.PropertyType;
if (val != null)
{
set = set.Where(StaticUtility.PropertyEquals<T>(prop, val, propType));
}
if (nvc.GetPairs().Where(p => p.Value == name).Where(p => p.Key.StartsWith("mDataProp")).Any())
{
var key = nvc.GetPairs().Where(p => p.Value == name).Where(p => p.Key.StartsWith("mDataProp")).FirstOrDefault().Key;
key = key.Replace("mDataProp", "sSearch");
val = nvc[key];
if (!String.IsNullOrEmpty(val))
set = set.Where(StaticUtility.PropertyEquals<T>(prop, val, propType));
}
}
return set;
} catch (Exception exc)
{
return set;
}
}
If I understand your request correctly, you basically want to search through your data and match any field for equality? If that's true, then simply add your matching data to a new set, and filter it by .Distinct() after the fact, to make sure you get one record of each. Something like so...
NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
var results = new IEnumerable<T>();
var generalSearch = nvc["sSearch"];
if (!string.IsNullOrWhiteSpace(generalSearch))
{
var generalSearchProperties = typeof(T).GetProperties();
foreach (var currentProperty in generalSearchProperties)
{
Type propType = currentProperty.PropertyType;
results.AddRange(set.Where(StaticUtility.PropertyEquals<T>(currentProperty, generalSearch, propType)));
}
}
return results.Distinct();
You could try to first create a BinaryExpression consisting of all the different options, then pass that expression to the Where() method of the query.
Assuming your StaticUtility class is used to create expressions, you might try something like the following:
NameValueCollection nvc = HttpUtility.ParseQueryString(Request.RequestUri.Query);
// Container for filter expression
BinaryExpression filter = null;
var generalSearch = nvc["sSearch"];
if (!string.IsNullOrWhiteSpace(generalSearch)) {
var generalSearchProperties = typeof(T).GetProperties();
foreach (var currentProperty in generalSearchProperties) {
Type propType = currentProperty.PropertyType;
if (filter == null) {
// Start with first filter expression
filter = StaticUtility.PropertyEquals<T>(currentProperty, generalSearch, propType);
} else {
// Add another filter using OR
BinaryExpression other = StaticUtility.PropertyEquals<T>(currentProperty, generalSearch, propType);
filter = BinaryExpression.OrElse(filter, other);
}
}
}
// Add actual filter to query
set = set.Where(filter);
I have a strongly typed class PersonExport. I initially get data into a DataTable and call the following method on the DataTable to convert it to List<PersonExport>:
public static List<T> ConvertToList<T>(DataTable dt, out string message)
{
message = string.Empty;
var list = new List<T>();
try
{
var columnNames = dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.ToList();
var properties = typeof(T).GetProperties();
list = dt.AsEnumerable().Select(row =>
{
var objT = Activator.CreateInstance<T>();
foreach (var pro in properties)
{
if (columnNames.Contains(pro.Name))
{
var value = row[pro.Name];
var typeName = value.GetType().FullName;
if (typeName == "MySql.Data.Types.MySqlDateTime")
{
var mySqlDateTime = (MySqlDateTime) value;
if (mySqlDateTime.IsValidDateTime)
{
value = Convert.ToDateTime(mySqlDateTime.ToString());
pro.SetValue(objT, value, null);
}
}
else
{
pro.SetValue(objT, row.IsNull(pro.Name) ? null : value, null);
}
}
}
return objT;
}).ToList();
}
catch (Exception ex)
{
message = (ex.InnerException != null) ? ex.InnerException.Message : ex.Message;
}
return list;
}
However, once I start removing columns from the DataTable returned, it no longer works because the columns in the DataTable don't match up with the properties in the PersonExport list.
I am eventually using the exported list here to export to excel, but it is not working since I have modified by DataTable and it can't Deserialize into a List<PersonExport>:
//Trying to get data into List<object>
List<object> persons = GetPersonExport(query, out message);
var exportData = new Dictionary<string, List<object>> { { "xldata", persons} };
//Deserialize to List<object> to export
var persons = JsonConvert.DeserializeObject<List<object>>(args["xldata"]);
The above line just returns a List of empty objects.
A few things got me thinking, but I am wondering what might be the best approach. I am using the EPPLUS library to export data to excel and it has the option of hiding columns, so would it be better to just export the whole object and hide columns you don't want, this way you avoid the anonymous type or what I can do is still get the whole object, but then convert it to a DataTable and then remove the columns? Thoughts?
All that you want is:
public IEnumerable<object> GetListOfObject()
{
foreach (var prod in TenMostExpensiveProducts().Tables[0].AsEnumerable())
{
yield return prod;
}
}
Or:
TenMostExpensiveProducts().Tables[0].AsEnumerable().Select (x => x).ToList<object>()
But you can get it work more elegant via linq like this:
from prod in TenMostExpensiveProducts().Tables[0].AsEnumerable()
where prod.Field<decimal>("UnitPrice") > 62.500M
select prod
Or like this (AsDynamic is called directly on DataSet):
TenMostExpensiveProducts().AsDynamic().Where (x => x.UnitPrice > 62.500M)
I prefer the last approach while is is the most flexible.
P.S.: Don't forget to connect System.Data.DataSetExtensions.dll reference
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);
}
StringBuilder sbRes = new StringBuilder();
jSon.Serialize(rows, sbRes);
ret = sbRes.ToString();