I have a List<string> where are stored database table column name.
I need to select only this column (where name is stored into list) from a c# linq query.
Is possible?
I Try this code but I don't know how I can place in select:
I try this code
items = items.ToList();
_items.Add(new FieldItem() { FieldName = "field1" });
_items.Add(new FieldItem() { FieldName = "field2" });
_items.Add(new FieldItem() { FieldName = "field3" });
_items.Add(new FieldItem() { FieldName = "field4" });
_db.Table.Where(a => a.TimeStamp > DateTime.Now.AddHours(-1)).Select(....);
Thanks
Get Dapper via NuGet.
After that put in using in your code:
using Dapper;
And you're good to go. All you would need to do now is(using the example you have posted):
using (YourDbContext _db = new YourDbContext())
{
return _db.Database.Connection.Query($"SELECT {string.Join(",", _items.Select(if => if.FieldName))} FROM Table WHERE TimeStamp > #TimeStamp;", new { TimeStamp = DateTime.Now.AddDays(-1) });
}
This methods would return IEnumerable which would have all of your fields. The results can be casted into IDictionary where the key is your column name and the value is the actual value.
So for instance, if we were to get the first row in the results with First(), we could access the field values like this:
var value = ((IDictionary<string, object>)result.First())["column_name"];
Finally, I use reflection.
In string list are stored property name.
Get a property by name, and get it's value.
In this way get all PropertyInfo for a class:
PropertyInfo[] propertyInfos;
propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public |
BindingFlags.Static);
When property name match, update property value with:
property.SetValue(child, parentProperty.GetValue(parent));
Isn't an optimized solution, but works.
Related
I want to convert a DataTable with 10 rows or more into an Array like this:
SqlConfiguration clist2 = new SqlConfiguration();
clist2.QueryString = "SELECT caption_id,caption,description FROM sws_template_detail WHERE template_id = 1";
DataTable db = clist2.GetRecords;
ListItem datalist = new ListItem();
foreach(DataRow row in db.Rows)
{
datalist = new ListItem
{
id = row["caption_id"].ToString(),
title = row["caption"].ToString(),
description = row["description"].ToString()
};
}
var section = new Section
{
title = "Title",
items = new ListItem[]
{
datalist
}
};
But the resulting data is only 1 row, how can I solve it?
You can do it in 1 line (well, 1 statement):
var section = new Section
{
title = "Title",
items = dataTable.Rows
.Cast<DataRow>()
.Select( row => new ListItem()
{
id = row["caption_id" ].ToString(),
title = row["caption" ].ToString(),
description = row["description"].ToString()
} )
.ToArray()
};
Though there's a lot of code smells going on here...
Why is an class named SqlConfiguration being used to execute a SQL query via a property named QueryString.
Public members in C#/.NET should be PascalCase not camelCase.
So it should be Section.Title, Section.Items, ListItem.Id, ListItem.Title, and ListItem.Description.
Don't use object-initializers for required members of an object, because there's no compile-time guarantees that they'll be populated.
If a ListItem must have an Id, Title, and Description then they should be passed-in as constructor parameters.
Using array-types (like ListItem[]) is usually not a good idea because array-types have the worst set of attributes in comparison to others: they're fixed-size but also mutable.
Whereas usually you want something resizable-and-mutable (e.g. List<T>) or completely immutable (e.g. ImmutableArray<T> or at least IReadOnlyList<T>).
Mutable elements
Resizable
Variance
T[] (Array types )
Yes
No
Unsafe
List<T>
Yes
Yes
Invariant
ImmutableArray<T>
No
No
Invariant
IReadOnlyList<T>
No
No
Covariant safe
try this
var items_array=new List<ListItem>();
foreach(DataRow row in db.Rows)
{
items_array.add(new ListItem
{
id = row["caption_id"].ToString(),
title = row["caption"].ToString(),
description = row["description"].ToString()
});
}
var section = new Section
{
title = "Title",
items = items_array.toArray()
};
Loading the data into a DataTable and then converting it into a List wastes both CPU and RAM. You can use an ORM like EF Core or Dapper to execute a query and return the results in the shape you want. For example, using Dapper, what you want is a single line:
var sql=#"select caption_id as Id, caption as Title, description
FROM sws_template_detail
WHERE template_id = 1";
var items=connection.Query<ListItem>(sql).ToArray();
Query<T> returns the results as an IEnumerable<T>. This is converted to an array using ToArray().
Dapper allows you to easily write parameterized queries instead of concatenating strings to construct a query:
var sql=#"select caption_id as Id, caption as Title, description
FROM sws_template_detail
WHERE template_id = #id";
var items=connection.Query<ListItem>(sql,new {id=1}).ToArray();
The query can be executed asynchronously using QueryAsync;
var items=(await connection.QueryAsync<ListItem>(sql,new {id=1}))
.ToArray();
I would like to know how to get the properties of my dynamic type.
This is the function to get the List,
var result = _files.GetFileContent(reportId).Result;
As example I get an object returned like this :
When I open it, you can see the properties I have :
The Idea is that I never know the properties. They can change over time. So I want a list which is filled with all the properties. So I can dynamically use them.
How Can I get the properties from the first item (ChargesDelta_DIFF_5, ChargesEfile_RIGHT,ChargesGecep_LEFT, etc)?
You can use reflection to get the properties out and convert it to a dictionary:
dynamic v = new { A = "a" };
Dictionary<string, object> values = ((object)v)
.GetType()
.GetProperties()
.ToDictionary(p => p.Name, p => p.GetValue(v));
If someone is still struggling with this (as I did), this might be useful.
Let's say data is the dynamic you want to list all properties from:
This worked for me
using System.ComponentModel;
...
dynamic data = new {
value1 = 12,
value2 = "asdasd",
value3 = 98,
value4 = "pgiwfj",
};
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(data))
{
Console.WriteLine("PROP: " + prop.Name);
}
...
Then it would output:
PROP: value1
PROP: value2
PROP: value3
PROP: value4
Source: https://social.msdn.microsoft.com/Forums/vstudio/en-US/251e4f3d-ce90-444a-af20-36bc11864eca/how-to-get-list-of-properties-of-dynamic-object-?forum=csharpgeneral
Is it possible to dynamically limit the number of columns returned from a LINQ to SQL query?
I have a database SQL View with over 50 columns. My app has a domain object with over 50 properties, one for each column. In my winforms project I bind a list of domain objects to a grid. By default only a few of the columns are visible however the user can turn on/off any of the columns.
Users are complaining the grid takes too long to load. I captured the LINQ generated SQL query then executed it within SQL Server Management Studio and verified its slow. If I alter the SQL statement, removing all the invisible columns, it runs almost instantly. There is a direct correlation between performance and the number of columns in the query.
I'm wondering if its possible to dynamically alter the number of columns returned from the LINQ generated SQL query? For example, here is what my code currently looks like:
public List<Entity> GetEntities()
{
using (var context = new CensusEntities())
{
return (from e in context.Entities
select e).ToList();
}
}
The context.Entities object was generated from a SQL View that contains over 50 columns so when the above executes it generates SQL like "SELECT Col1, Col2, Col3, ... Col50 FROM Entity INNER JOIN...". I would like to change the method signature to look like this:
public List<Entity> GetEntities(string[] visibleColumns)
{
using (var context = new CensusEntities())
{
return (from e in context.Entities
select e).ToList();
}
}
I'm not sure how to alter the body of this method to change the generated SQL statement to only return the column values I care about, all others can be NULL.
Something like this should work:
List<string> columns = new List<string>();
columns.Add("EmployeeID");
columns.Add("HireDate");
columns.Add("City");
Add columns to your list ^.
var result = Class.ReturnList(columns);
Pass the List to a method ^.
public static List<Entity> ReturnList(List<string> VisibleColumns)
{
StringBuilder SqlStatement = new StringBuilder();
SqlStatement.Append("Select ");
for (int i = 0; i < VisibleColumns.Count; i++)
{
if (i == VisibleColumns.Count - 1)
{
SqlStatement.Append(VisibleColumns[i]);
}
else
{
SqlStatement.Append(VisibleColumns[i]);
SqlStatement.Append(",");
}
}
SqlStatement.Append(" FROM Entity");
using (var ctx = new DataClasses1DataContext())
{
var result = ctx.ExecuteQuery<Entity>(SqlStatement.ToString());
return result.ToList();
}
}
This basically just makes a SELECT statement with all the fields you passed in with the VisibleColumns list.
In this case, the SQL statement that will be generated by the strings in the VisibleColumns list is:
Select EmployeeID, HireDate, City From Employee
(note: i used the Northwind database to try this out, hence the EmployeeID etc column names. You should replace them with your own, obviously.)
It is not trivial to do this dynamically, but if you have a limited set of combinations of columns you want to retreive you can do an explicit select like this:
public List<Entity> GetEntities()
{
using (var context = new CensusEntities())
{
return (from e in context.Entities
select new
{
col1 = e.col1,
col4 = e.col4,
col5 = e.col5,
}
).ToList()
.Select(x=>new Entity{col1 = x.col1, col4 = x.col4, col5 = x.col5}).ToList();
}
}
The extra select step is necessary because LINQ2SQL won't create partial entities for you.
Create a method for each common combination of columns (especially the initial) the users wants to retrieve.
However to make this dynamic you can build a query with you entity stored as a property in an anonymous class and collect your result properties in another anonymous class in second property in the same anonymous class. Finally you select your entities from the collected objects into objects of the correct type.
public List<Entity> GetEntities()
{
using (var context = new CensusEntities())
{
var combinedResult = (from e in context.Entities
select new {
Entity = e,
CollectedValues = new
{
// Insert default values of the correct type as placeholders
col1 = 0, // or "" for string or false for bool
col2 = 0, // or "" for string or false for bool
// ...
col49 = 0, // or "" for string or false for bool
col50 = 0, // or "" for string or false for bool
}
);
// Then copy each requested property
// col1
if (useCol1)
{
var combinedResult = (from e in combinedResult
select new {
Entity = e,
CollectedValues = new
{
col1 = e.Enitity.col1, // <-- here we update with the real value
col2 = e.CollectedValues.col2, // <-- here we just use any previous value
// ...
col49 = e.CollectedValues.col49, // <-- here we just use any previous value
col50 = e.CollectedValues.col50, // <-- here we just use any previous value }
);
}
// col2
if (useCol2)
{
// same as last time
col1 = e.CollectedValues.col1, // <-- here we just use any previous value
col2 = e.Enitity.col2, // <-- here we update with the real value
// ...
}
// repeat for all columns, update the column you want to fetch
// Just get the collected objects, discard the temporary
// Entity property. When the query is executed here only
// The properties we actually have used from the Entity object
// will be fetched from the database and mapped.
return combinedResult.Select(x => x.CollectedValues).ToList()
.Select(x=>new Entity{col1 = x.col1, col2 = x.col2, ... col50 = x.col50}).ToList();
}
}
There will be lots of code, and a pain to maintain, but it should work.
If you are going this route I suggest that you build a code generator that builds this code with reflection from your LINQ context.
Try something like this
using (var context = new CensusEntities())
{
var q = from e in context.Entities
select e.myfield1,e.myfield2;
return q.Tolist();
}
The resulting query should be lighter and also all the data conversion that goes underneath.
But if you really need to build dynamic input, I think some dynamic sql should be involved. So
build the dynamic SQL and get a data table
use a datatable to a dynamic object conversion as shown here
How can I convert a DataTable into a Dynamic object?
BTW a lot of hard work, I think you should considered using the first block of code.
I have a function which searches some articles in the Sitecore content items and give me the value. So far I have build up my indexes and it is showing in my IndexViewer. But the return of the function is 0. I looked up this link: http://sitecoregadgets.blogspot.com/2009/11/working-with-lucene-search-index-in_25.html for more information.
protected IEnumerable<Item> ShowHomePageNews(int numOfArticles, string stringofCountries)
{
List<Item> items = new List<Item>();
Sitecore.Search.Index indx = SearchManager.GetIndex("newsArticles");
using (IndexSearchContext searchContext = indx.CreateSearchContext())
{
var db = Sitecore.Context.Database;
CombinedQuery query = new CombinedQuery();
QueryBase catQuery = new FieldQuery("countries", stringofCountries); //FieldName, FieldValue.
SearchHits results = searchContext.Search(catQuery); //Searching the content items by fields.
SearchResultCollection result = results.FetchResults(0, numOfArticles);
foreach (SearchResult i in result)
{
items = result
.Where(r => !r.Title.StartsWith("*"))
.Select(r => db.GetItem(new Sitecore.Data.ItemUri(r.Url).ToDataUri()))
.ToList();
//Lucene.Net.Documents.Field url = i.Document.GetField("_url");
//Sitecore.Data.ItemUri itemUri = new Sitecore.Data.ItemUri(url.StringValue());
//Sitecore.Data.Items.Item item = Sitecore.Context.Database.GetItem(itemUri.ToDataUri());
//items.Add(item);
}
}
return items;
}
Over here the result is 0. What I am doing wrond here?
This is the snapshot of what I am seeing in my IndexViewer:
EDIT:
I am passing a "NZ" in the 'catQuery' and I am getting the result back. Because in my index viewer I am seeing the Field Name = _name, which contains NZ in it. I got this part. However, I want my every field to be indexed. I am seeing only 3 fields in my IndexViewer: _url, _group & _name.
So your countries should be tokenized by the indexer. As a multilist, they will be tokenized by GUID. Searching for a single country by GUID with your code above should work. However, if you want to search for multiple countries, where any of the passed in countries can trigger a match, you need to structure your query differently.
CombinedQuery query = new CombinedQuery();
//apply other filters here to query if need be
//and country filter by creating a new clause (combinedquery) and "ORing" within it (QueryOccurance.Should)
CombinedQuery query3 = new CombinedQuery();
//here you would actually iterate over your country list
query3.Add(new FieldQuery("countries", country1GUID), QueryOccurance.Should);
query3.Add(new FieldQuery("countries", country2GUID), QueryOccurance.Should);
query.Add(query3, QueryOccurance.Must);
I have the following class in my C# .NET 3.5 win forms app:
class Field {
string objectName;
string objectType;
string fieldName;
string fieldValue;
}
and a List fieldList that is a datasource for a checkedlistbox. This listbox shows all the distinct objectNames from my fieldList collection.
I want to create another checkedlistbox that contains fieldNames, but only shows fieldnames that have an associated checked objectName in the first list box.
So my question is how can I query the DataSource of the original list of objectNames to return the distinct set of fieldNames that are associated with a selected objectName?
That is not very easy to read so I will give an example:
Field1 {
objectName = 'objA'
FieldName = 'FieldA'
}
Field2 {
objectName = 'objA'
FieldName = 'FieldB'
}
Field3 {
objectName = 'objB'
FieldName = 'FieldA'
}
Field4 {
objectName = 'objC'
FieldName = 'FieldC'
}
So suppose in my checkbox I select objectNames objA and objB. Then my returned fields would be 'FieldA' and 'FieldB'.
How can I achieve this using LINQ or filtering my generic list of Fields? Can I utilise the 'select' or 'where' methods that are available to a list?
First, read the object names into an array or list; I'll fake that part. Then it should be something like:
string[] objectNames = { "objA", "objC" };
var hashSet = new HashSet<string>(objectNames);
var qry = (from row in data
where hashSet.Contains(row.objectName)
select row.fieldName).Distinct().ToList();
(edit)
To get the selected names (the bit I faked) you could try (untested):
var selectedNames = namesCheckedListBox.CheckedItems.Cast<Field>()
.Select(field => field.objectName);
var hashSet = new HashSet<string>(selectedNames);
(note no need to use Distinct() in the above, since HashSet<T> does that anyway)
var selectedNames = ... // List of selected names
var selectedFields = (from f in fieldList
where selectedNames.Contains(f.objectName)
select f.FieldName).Distinct().ToList();