I have dynamic list of customers IEnumerable<Customer>
now I want to have the disctinct company names from that list?
I thought I could do something like
dynamic cur = (from c in result.Customers
select g.CompanyName).Distinct();
but learned today that I can't...
how can I build a query like this?
What you are doing in code and what you are asking in the title of your question are two different things.
If you want IEnumerable<dynamic> you must do the following:
IEnumerable<dynamic> cur = (from c in result.Customers
select g.CompanyName).Cast<dynamic>().Distinct();
from c in result.Customers select g.CompanyName returns IEnumerable<string>.
Cast<dynamic>() returns IEnumerable<dynamic>.
Distinct() returns distinct members of the enumerable.
Distinct() uses, by default, the default equality comparer EqualityComparer<T>. This examines the type being enumerated and tries to figure out how to handle it (the link describes this in detail).
This all works as advertised, unless the type being handled dynamically can't be handled by the default equality comparer. In this case, you'll have to use the override that takes a custom equality comparer.
As long as the Customer class has a member CompanyName, you can definitely do the following:
var companies = (from c in result.Customers
select c.CompanyName).Distinct();
There is no advantage to using the dynamic keyword over var here, other than the fact that it will prevent compiler errors from appearing.
Related
I use nhibernate mapping by code, I want to make this expression dynamicllay (with a nested object)
I have a class event that has a relation many to one with Event state/and I want to grouping by code in the table EventState
var grouping = query.GroupBy(x => x.EventState.Code)
It works for me with a simple property, here is my code:
var arg = Expression.Parameter(type, categoryColumnName);
var bodyy = Expression.Convert(Expression.Property(arg, categoryColumnName), typeof (object));
var lambdaGroupBy = Expression.Lambda<Func<Operation, object>>(bodyy, arg);
var keySelector = lambdaGroupBy.Compile();
var grouping = query.GroupBy(keySelector);
return grouping.Select(a => new PieChartObject { Category = a.Key.ToString(), Value = a.Count().ToString() }).ToList();
But I can't do it with nested object.
GroupBy will partition your query by what you provide as key selector. To determine whether two items in your query have the same key, it uses the default comparer of the given type. For object, this is uses the Equals and GetHashCode methods which in turn for strings mean that the contents of the strings are identical. If you use a class, by default the reference identity is used, so I think that GroupBy isn't doing anything in your case because the keys you provided are not identical, even though they may have the same values.
So there are two valid solutions: You can either override Equals and GetHashCode in your nested object class, or you can provide a custom key comparer to GroupBy, if you want this behavior only for this particular query. But I guess, as you want to be generic, implementing Equals and GetHashCode would be a better option. The only exception is of course when you cannot do this, e.g. because it is a compiler-generated class. In that case, there is few things you can do about that.
I have a question, my friend and I are doing code, and he did two methods that I don't exactly understands.
public static List<Borrow> GetDistinctBorrows(List<Borrow> list)
{
var Result = (from bor in list group bor by new { bor.BookAccessor, bor.ReaderAccessor } into dist select dist.First()).ToList();
return Result;
}
and a second one
public static List<Borrow> GetDistinctBorrows(List<Borrow> list)
{
var Result = list.GroupBy(x => new { x.ReaderAccessor, x.BookAccessor }).Select(y => y.First()).ToList();
return Result;
}
Those methods have the same functionality, but one are written with LINQ, and a second one with lambda expressions.
Can someone explain to me, how they work (especially the fragment with 'new' word)?
The part with new word is how you define instances on Anonymous Types.
Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to explicitly define a type first. The type name is generated by the compiler and is not available at the source code level. The type of each property is inferred by the compiler.
You create anonymous types by using the new operator together with an object initializer. For more information about object initializers, see Object and Collection Initializers (C# Programming Guide).
As a side note, your queries are equivalent, because compiler will transform the first one onto the second one as part of compilation process. Read more about that on MSDN: Query Syntax and Method Syntax in LINQ (C#)
Most queries in the introductory Language Integrated Query (LINQ) documentation are written by using the LINQ declarative query syntax. However, the query syntax must be translated into method calls for the .NET common language runtime (CLR) when the code is compiled. These method calls invoke the standard query operators, which have names such as Where, Select, GroupBy, Join, Max, and Average. You can call them directly by using method syntax instead of query syntax.
The functions gets a list of distinct items from the input list, where ReaderAccessor and BookAccessor determine equality. Duplicated items from the input list is discarded.
They work by grouping by a new anonymous object defined by the two properties (this is where the new keyword is used), creates an alias dist and then taking the first one, essentially discarding the rest.
In Linq to Object (Enumerables)
How does the default comparer resolve the following?
//The following is essentially a select distinct
var x = from student in class
group student by new {student.MajorId, student.GradeId} into performanceStudentGroup
select new { performanceStudentGroup.Key.MajorId, performanceStudentGroup.Key.GradeId};
Obviously in order for the above to work, the framework has to compare 2 anonymous types to check if they belong in the same group.
How does it do that? How is it able to check for something more than the reference pointers?
How is that comparer different than the following code:
var y = (from student in class
select new { student.MajorId, student.GradeId}).Distinct();
Following the MSDN documentation on Anyonymous Types
Because the Equals and GetHashCode methods on anonymous types are defined in terms of the Equals and GetHashcode methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.
The anonymous type will be created and has an Equals() and GetHashCode() implementation based on the properties. If the properties will be the same, these these two methods will return the same result. I imagine there's some collection in the back that holds the different instances of the anonymous type.
When the compiler generates an anonymous type, it also generates Equals() and GetHashCode() methods to compare it by value. You can see this in a decompiler.
The default EqualityComparer doesn't know anything about anonymous types; it simply calls these methods.
IEnumerable<Department> myQuery = (from D in myContext.Departments orderby D.DeptName select D);
var myQuery = (from D in myContext.Departments orderby D.DeptName select D);
What is the difference between these two statements above? In my little asp.net/C#/ EF4.0 app I can write them either way, and as far as how I want to use them, they both work, but there has to be a reason why I would choose one over the other?
(from D in myContext.Departments orderby D.DeptName select D);
returns an object of type IQueriable<Department> which in turn implements IEnumerable<Department>
while you use the var keyword in here the compiler replace it with IQueriable<Department>
The second one is shorter (assuming type of D is Department).
(actually, the return type of the query may be something other than IEnumerable, like IQueryable but the point is, the type will be statically inferred from the right hand side of the assignment operator instead of being explicitly mentioned in code).
syntactic convenience
I believe in the 2nd case the type of myQuery is an IQueryable<Department> rather than IEnumerable. If you don't need anything specific to an IQueryable that you can't do with an IEnumerable then they behave the same.
The var keyword is just for convenience when the compiler can figure out the type without spelling it out. So instead of
MyReallyLongGenericClassName<SomeOtherType> myObject = new MyReallyLongGenericClassName<SomeOtherType>();
You can just write var myObject = new MyReallyLongGenericClassName<SomeOtherType>();
With var the compiler infers the type of myQuery. It would probably endup being an IQueryable<Department> rather than an IEnumerable<Department>.
The only difference here is that you're not declaring yourself the type of myQuery. You're taking advantage of a feature named Type Inference. Indeed the type returned will be IQueryable<Department> where the first statment explicitly types the variable as IEnumerable.
i have list of objects i need to sort the list based on object's property1 and i need to sort again the resultant list with object's property2 without loosing the grouping done in first sorting ....
for ex:
obj has 2 property name and location
i need to have a final list of objects which has been sorted with region and objects of same region should be sorted by name...
(Assuming you don't have LINQ available to you, which makes this trivial.)
If you look in MiscUtil, you'll find two useful classes: ProjectionComparer and LinkedComparer (IIRC).
ProjectionComparer basically implements the LINQ "order by" concept - you specify how to convert a source element to a key value, and the comparer will order by those key values.
LinkedComparer takes two comparers and returns a new comparer which uses the "primary" comparer first, and the "secondary" comparer if values are equal with respect to the primary one.
Create two projection comparers (one for each property) and then a linked comparer with the two of them, then pass that to List<T>.Sort. Let me know if you need a full code sample, but it would be something like (using C# 3):
var comparer = new LinkedComparer<Foo>
(ProjectionComparer<Foo>.Create(x => x.FirstProperty),
ProjectionComparer<Foo>.Create(x => x.SecondProperty));
(In C# 2 you could use anonymous methods, they'd just be a bit more long-winded.)
Sounds like you want to use LINQ's orderby and thenby syntax.
A List has a Sort method which takes a Comparision delegate as an argument.
There are also overloads where you can pass in your own comparer.
So, you can write a class which implements IComparer. Then, in the implementation of this class, you write the code where you compare the 2 objects on the properties you want.