In C#, I'm going to use lambda expression, I have such a code
var item = dbContext.Products.ToList();
How can i get a property of Product table.
try this
var item = dbContext.Products.FirstOrDefault().Name;
With Lamba expression normally you can access and read information from "list" or in this case, IQueryable objects.
With your code you can access to objects with something like this:
var item = dbContext.Products.FirstOrDefault();
// item may be null if products table is empty
if (item != null)
{
// now you can access at object properties (example)
var data = item.PropertyData;
}
Your question may open others way that including reflection for exploring object without well known class definition...
If you want to get the property for each product with lambda expression, then you should make a lambda expression like x => x.Prop when you do your query
if (dbContext.Products != null){
var list = dbContext.Products.ToList();
var query = list.Select(x => x.Prop //your property will appear here...
}
Related
In a C# project, I want to be able to create a function that accepts an IQuereable<User> object along with multiple lambda's expressions then converts it into a different object. However, instead of pulling all the available properties from the database, I want to pull only the properties that are provided to the function. Here is the logic that I think I need to follow
Figure out what properties that I need to select
Construct an IEnumerable from the IQueryable by specifying which properties that are needed.
Iterate over every property that was selected and create the Student object.
In other words, if I call .ToList() on the IQuereable<User> users object, the query will select * from the databse table which pull all available columns. Instead I want to select only the properties that are passed as labda expressions.
Here is my code
public IEnumerable<Student> Make(IQuereable<User> users, Expression<Func<User, dynamic>> keyProperty, params Expression<Func<User, dynamic>>[] propertiesToSelect)
{
var students = new List<Student>();
// Make a distinct list of lambda's expressions that I need to select
var props = propertiesToSelect.ToList();
props.Add(keyProperty);
props = props.Distinct().ToList();
// TO DO!!! Some how, I need to only select the properties that are in **props** array insted of pulling all available properties
var selectableUsers = users.Select(/**/).ToList();
foreach(var user in selectableUsers)
{
var student = new Student();
foreach(Expression<Func<User, object> exp in props)
{
var prop = GetPropertyInfo(user, exp)
object value = prop.GetValue(user, null);
// Set the property student property
// Do somthing with prop.Name...
// Do something with value...
}
students.Add(student);
}
return strudents;
}
Question How can I use LINQ to select only the list of Expressions
This may be a case for using a stored procedure and dynamic SQL to build your initial query and control the contents of the SELECT statement.
The other option I see is to define a DTO object and leverage the AutoMapper Queryable Extensions and use the Explicit Expansion functionality to control the data to return.
I have a List<> of abstract objects that contains different types of objects.
I am trying to grab all the items of a certain type and set those items to their own List<>.
This is not working -
//myAbstractItems is a List<myAbstractItem>
//typeAList inherents from myAbstractItem
var typeAList = ((List<itemTypeA>)myAbstractItems.Where(i => i.GetType() == typeof(itemTypeA)).ToList());
The casting (List<itemTypeA>) appears to be failing.
Use the OfType extension method:
var typeAList = myAbstractItems.OfType<itemTypeA>().ToList();
From the documentation...
The OfType(IEnumerable) method returns only those elements in source that can be cast to type TResult.
A good old loop should be fine :
List<itemTypeA> res = new List<itemTypeA>();
foreach(var item in myAbstractItems)
{
itemTypeA temp = item as itemTypeA;
if (temp != null)
res.Add(temp)
}
Try using Where this way:
var typeAList = myAbstractItems.Where(i => i.GetType() == typeof(itemTypeA)).Select(item => item as itemTypeA).ToList())
Another way you could do this is using the OfType() method:
var typeAList = myAbstractItems.OfType<itemTypeA>().ToList();
This method basically performs the following operation:
var typeAList = myAbstractItems.Where(i=>i is itemTypeA).Select(i=>i as itemTypeA).ToList();
Keep in mind that this will fail if any element of the source collection is a null reference.
This will work for all itemTypeAs (and more derived types).
var typeAList = myAbstractItems.Select(i => i as itemTypeA).Where(i => i != null).ToList();
EDIT: edited as per Rawling's comment.
I'm trying to update an entityCollection
Here is my linq:
itemFromDb.MamConfigurationToBrowser_V1 =
(EntityCollection<MamConfigurationToBrowser_V1>) itemFromDb.MamConfigurationToBrowser_V1
.Select(browserEfItem =>
FillFromUi(browserEfItem,
item.MamConfigurationToBrowser_V1
.Single(browserUiItem => browserUiItem.BrowserVersionId == browserEfItem.BrowserVersionId)))
.ToList().AsEnumerable();
However I get a runtime casting error:
Unable to cast object of type
'System.Collections.Generic.List1[Conduit.Mam.MaMDBEntityFramework.MamConfigurationToBrowser_V1]'
to type
'System.Data.Objects.DataClasses.EntityCollection1[Conduit.Mam.MaMDBEntityFramework.MamConfigurationToBrowser_V1]'.
Why is that? As I'm doing linq to entity, no?
You are creating a List<MamConfigurationToBrowser_V1> with your second-last call ToList() in your Linq expression and then you try to cast this list to an EntityCollection<MamConfigurationToBrowser_V1. I would recommend to create a new EntityCollection and add the results from the LINQ query to this collection, like so:
var collection = new EntityCollection<MamConfigurationToBrowser_V1>();
var processedItems = itemFromDb.MamConfigurationToBrowser_V1
.Select(browserEfItem =>
FillFromUi(browserEfItem,
item.MamConfigurationToBrowser_V1
.Single(browserUiItem => browserUiItem.BrowserVersionId == browserEfItem.BrowserVersionId)))
.ToList();
foreach(var item in processedItems)
{
collection.Add(item);
}
Important: your code seems to mix database concerns with business logic and personally I never used an EntityCollect<T> directly in my code. I don't know your context but maybe you should consider using the Repository and Unit of Work pattern. Search for them on Google.
ItemFromDB is an unique object? I mean that if itemFromDB is not a list, yo are trying to convert a unique object to a list.
instead of .ToList().AsEnumerable() you can try to use .FirstOrDefault().
I have a rather complex database, where we are using Linq to SQL. I'm creating a model layer where I would like to only have one method. But my problem is that we often like to order the collection. Is it possible somehow to accomplish something like this:
public static List<Object> GetObject(Object.Property)
{
return some Linq.ToList();
}
I know I can use linq on my list afterwards.
Hmm it was maybe a bit to diffuse question.
OK I solved it with reflection and a string in the argument..
MyObjectDataDataContext context = new MyObjectDataDataContext ();
PropertyInfo[] piArray = context.MyObject.GetType().GetProperties();
PropertyInfo pi = piArray.FirstOrDefault(s => s.Name == "property");
if (pi != null)
{
return context.MyObject.OrderBy(t => pi.PropertyType);
}
I guess you are trying to access the same data, but depending on a 'column' criteria, return the data sorted?
Once you have the IEnumerable data, you can sort it as follows:
list.OrderBy(t => t.ColumnYouWantToSortBy)
As in the following documentation
I'm trying to build a method that will receive a Linq table, and should return a List<> of values that will be a DropDownList Datasource.
This is what I've got till now:
public static List<Structs.NameValuePair> GenDropDownItens<T>(string ValueField , string TextField ) where T: class
What i don't know how to do is, query the table getting only the fields that are passed ( ValueField, TextField)...
Tks!
Project the result of your LINQ2SQL query into a System.Collections.Generic.KeyValuePair object like so:
ddl.DataSource = DataContext.Table.Select(o => new KeyValuePair<string, string>(o.ID, o.DisplayField));
ddl.DataBind();
You will then want to set the DataValueField and DataTextField attributes on the DropDownList to "Key" and "Value" respectively.
Why not just do something like;
var dropDownValues = dataContext.SomeTable.ToDictionary(
s => s.Name,
s => s.Value
);
foreach(var item in dropDownValues) {
var OptionName = item.Key;
var OptionValue = item.Value
};
Hope this helps, I really don't think you need to create a while method. But if you wanted to I would say have it take a IDictionary object, and convert it from there.
Table.Select( t => t.field1, t.field2 )
Also check out Scott Gutherie's blog series here.
Are you trying to do something like the following with your method
GetDropDownItems("Gates", "LastName") ????
If so, included as part of the SDK samples is a project called DynamicQuery. Using this you can basically create a text version of the query you want. You could do something like
"LastName == 'Gates'"
However, it is just as easy to build the expression tree yourself. The best way to learn what the expressions tree's look like is to use the ExpressionTreeVisualizer VS debugger add in (note this is also another sample contained in the SDK CSharpSamples). It would be something like
ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
var expression = Expression.Equals(Expression.Property(parameter, "LastName"), Expression.Constant("Gates")
If "Key" and "Value" are strings that represent the name of the properties you would like to get, and they are known only at runtime... here's your code:
private static Func<T, DictionaryEntry> GetNameValuePairFunc<T>(string valueField, string textField)
{
Func<T, DictionaryEntry> result = (item) =>
{
object key = typeof(T).GetProperty(valueField).GetValue(item, null);
object text = typeof(T).GetProperty(textField).GetValue(item, null);
return new DictionaryEntry(key, text);
};
return result;
}