Linq Group By Issue - can't get the syntax right - linq

For some reason I am totally stuck on the syntax for LINQ Group in vb.net - can somebody help me sort out the following?
I have 5000 objects like this:
Public Class ExpressionReturn
Implements IComparable(Of ExpressionReturn)
Public Property Price As Price
Public Property Value As Nullable(Of Decimal)
Public Property Expression As Expression
Public Property Rank As Single
End Class
I am trying to group them together on price.priceid (an integer) and then return a sum of the ranks to have a series of object such as this:
Public Class RankReturn
Public Property Price As Price
Public Property Expression As Expression
Public Property RankSum As Single
End Class
I'm stuck on the syntax for Group By in Linq... can anyone help?

Thanks for coming back to me - after playing with the code with a clear head it seems a big difference between c# (which has most of the examples) and vb.net is that you seem to have to return the same objects in the select statement as are being grouped.
I've now ditched this approach as grouping is much slower than I expected - I've used a dictionary to store the sum that I need which is much quicker 5ms compared to 700ms!

Related

Spring Sorting with Nulls_Last Handling not working

I created a sort rule like this for sorting my list:
Sort sort = new Sort(new Sort.Order(Sort.Direction.ASC,"productOrder", Sort.NullHandling.NULLS_LAST), new Sort.Order(Sort.Direction.ASC,"producedYear", Sort.NullHandling.NULLS_LAST));
with this rule I want to sort the productOrder first, and then if the productOrder is the same then the producedYear will be compared and sorted. If there are null values presented, it should be sorted at the end of the list. productOrder will have type Long and producedYear will have type Double.
My Repository interface extends the JpaRepository:
public interface ProductRepository extends JpaRepository<Product, String> {
List<Product> findByDisabledAndValid(int disabled, int valid, Sort sort);
}
But the sorted list I received is containing the null values always at the beginning of the list. This means the null values will be sorted first, then come the productOrder, and finally the producedYear will be sorted. It seems that the third parameter that I defined on my Sort.Order method is not working.
Does anyone have an idea why? Thank you very much
Instead of using the Sort.NullHandling.NULLS_LAST integrated with Spring, I solved the above problem by creating my own Sort function, like this:
Collections.sort(resultList, Comparator
.comparing(Product::getProductOrder, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(Product::getProducedYear, Comparator.nullsLast(Comparator.naturalOrder())));
Hope this help if someone also faces the same problem.
Regards!

Search objects by comparing the objects in the object, which is in the list

There's a possibility to find a objects using similar expression as below?
List<Object> findPracticesByHeadquartersCityRegionOrInstitutionsCityRegion(List<Region> regions)
The object looks like this:
public class Practice{
private Headquarters headquarters;
private List<Institution> institutions;
}
The Headquarters and an Institution have the variable City.
City have the variable of Region.
Problem is a List. Is possible to did something similar to loop inside query to check every object inside this list?
I use mongodb.
Regards,
Thank you in advance

Liferay comparator not working

I am using method for finding structure articles:
List<JournalArticle> articles = JournalArticleLocalServiceUtil.getStructureArticles(groupId, "15566", 0, 10000, comparator);
comparator is instance of class:
public class OrderByEventsStartDate extends OrderByComparator{
public int compare(Object o1, Object o2){
System.out.println("comparator test");
return 1;
}
}
Message is never printed and results are not sorted... Any help, please?
results are not sorted...
Because you are always returning 1.
Now to create an OrderByComparator you need to do something more.
If you look at the source code as to how the OrderByComparator is used by the different persistence methods you would get some idea.
Also a look at some of Liferay's implemented Comparators will shed some light as to what you need to do:
Journal Comparators - You can check the ArticleTitleComparator
UserFirstNameComparator
A super-short tutorial on implementing OrderByComparator in liferay
You would require to create 3 fields:
public static final String ORDER_BY_ASC - Specifies the field with which you want to order the results. In the ascending manner.
public static final String ORDER_BY_DESC - Specifies the field with which you want to order the results. In descending order.
public static final String[] ORDER_BY_FIELDS - Specifies the different fields required for sorting (refer UserFirstNameComparator for multiple fields).
Implement the compare method on the field you would like to sort
Impement the getOrderBy() method - refer ArticleTitleComparator
Impement the getOrderByFields() method - refer ArticleTitleComparator
Impement the isAscending() method, required in compare and getOrderBy methods to decide whether it is asc or desc - refer ArticleTitleComparator
Message is never printed and
Because you have not implemented these methods, it ignores the OrderByComparator you have passed. You can check the source code of the method you are using JournalArticleLocalServiceImpl#getStructureArticles
Hope this helps.

Changing values of an object in a LINQ-statement

I want to add some calculated properties to an EntityObject without loosing the possibility of querying it agains the database.
I created a partial class and added the fields I need in the object. Than I wrote a static function "AttachProperties" that should somehow add some calculated values. I cannot do this on clientside, since several other functions attach some filter-conditions to the query.
The functions should look like this:
return query.Select(o =>
{
o.HasCalculatedProperties = true;
o.Value = 2;
return o;
});
In my case the calculated value depends on several lookups and is not just a simple "2". This sample works with an IEnumerable but, of course, not with an IQueryable
I first created a new class with the EntityObject as property and added the other necessary fields but now I need this extended class to be of the same basetype.
First, in my opinion changing objects in a Select() is a bad idea, because it makes something else happen (state change) than the method name suggests (projection), which is always a recipe for trouble. Linq is rooted in a functional programming (stateless) paradigm, so this kind of usage is just not expected.
But you can extend your class with methods that return a calculation result, like:
partial class EntityObject
{
public int GetValue()
{
return this.MappedProp1 * this.MappedProp2;
}
}
It is a bit hard to tell from your question whether this will work for you. If generating a calculated value involves more than a simple calculation from an object's own properties it may be better to leave your entities alone and create a services that return calculation results from an object graph.
Try something like this:
return from o in collection
select new O()
{
OtherProperty = o.OtherProperty,
HasCalculatedProperties = true,
Value = 2
};
This will create a copy of the original object with the changes you require and avoid all the messiness that come with modifying an entity in a select clause.

help with expression for nHibernate linq provider extension

I'm working on a custom linq extension for nHibernate by extending the BaseHqlGeneratorForMethod. The technique is documented here:
http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html
I've had success with implementing these for various types of operations, but I must say - converting a simple linq expression to its full expression tree is not easy! I'm stuck on one now.
For this example, I have three entities. Employee, Group, and EmployeeGroup. The EmployeeGroup class sets up a many-to-many relationship between Employee and Group. I must specifically create the intermediate class because there are additional properties to track like specific permissions each employee has in each group. So there are two one-to-many relationships, rather than an nHibernate many-to-many relationship.
Now say I want to get all groups that contain a specific employee. I can write this query:
var groups = session.Query<Group>()
.Where(g => g.EmployeeGroups.Any(eg => eg.Employee == employee));
This works fine, but it's a lot to type. I'd much rather be able to do this:
var groups = session.Query<Group>().Where(g => g.HasEmployee(employee));
I start by creating an extension method like so:
public static bool HasEmployee(this Group group, Employee employee)
{
return group.EmployeeGroups.Any(eg => eg.Employee == employee);
}
This works when querying a local list of groups, but not against the nHibernate session. For that, I have to also create a linq extension and register it. Just like in the article (linked above), I create a GroupHasEmployeeGenerator class that extends BaseHqlGeneratorForMethod. I set its .SupportedMethods property to reference my HasEmployee extension method.
Where I get lost is in the override to BuildHql. The expression to build gets complicated pretty fast. I figure since I'm replacing the .Any clause - a good place to start is with the source for the built-in AnyHqlGenerator class. But that doesn't take into account that the source is a property of the original element, and it also doesn't take into account that I don't have a lambda expression to represent the where clause. I need to build these parts manually.
There's no point in posting my attempts so far, as they've all be quite far from anything that would work.
Will someone please help me convert this simple expression into the approprate set of methods for the BuildHql method override?
If there is any better documentation out there for this, please let me know. Thanks.
I know this question is a year old, but I ran into a very similar issue when implementing BaseHqlGeneratorForMethod today.
The input to BuildHql contains a collection of System.Linq.Expressions.Expression arguments that are passed to your extension method. Using these arguments, you can build an expression tree that represents the implementation of your extension method. If the resulting expression is something NHibernate.Linq supports, then you can transform that expression to a subtree of Hql using the provided IHqlExpressionVisitor.
In your example:
public static bool HasEmployee(this Group group, Employee employee)
{
return group.EmployeeGroups.Any(eg => eg.Employee == employee);
}
This would become something similar to this:
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
var AnyMethod = EnumerableHelper.GetMethod("Any", new[] {typeof(IEnumerable<EmployeeGroup>), typeof(Func<EmployeeGroup, bool>)}, new[] {typeof(EmployeeGroup)});
var EmployeeGroupsProperty = ReflectionHelper.GetProperty<Group>(g => g.EmployeeGroups);
var EmployeeProperty = ReflectionHelper.GetProperty<EmployeeGroup>(eg => eg.Employee);
var EmployeeGroupParameter = Expression.Parameter(typeof(EmployeeGroup));
var EmployeeGroupPredicate = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(EmployeeGroupParameter, EmployeeProperty), arguments[1]), EmployeeGroupParameter);
var CallExpression = Expression.Call(AnyMethod, Expression.MakeMemberAccess(arguments[0], EmployeeGroupsProperty), EmployeeGroupPredicate);
return visitor.Visit(CallExpression);
}
I can't really test this specific example, but the same approach worked for me when providing support for my own extension method.

Resources