vb.net LINQ to Object grouping by create date - vb.net

I have a .net webapi endpoint that currently returns an array of objects (JSON).
I'm trying to group the items by the created date, but i can't work out the LINQ statement to achieve this.
Class:
Public Class mImage
Public Property fileName As String
Public Property id As Guid
Public Property description As String
Public Property createDate As DateTime
End Class
Public Class mImageParent
Public Property groupDate As DateTime
Public Property images As List(Of mImage)
Public Property groupCount As Integer
End Class
My current JSON return looks like this:
obj: [
{"fileName":"a","id":"1","createDate":"1-1-2020"},
{"fileName":"b","id":"2","createDate":"1-1-2020"},
{"fileName":"c","id":"3","createDate":"2-1-2020"}
]
Where i'm trying to return it as:
obj: {"groupDate":"1-1-2020",
"images": [
{"fileName":"a","id":"1","createDate":"1-1-2020"},
{"fileName":"b","id":"2","createDate":"1-1-2020"}
]},
{"groupDate":"2-1-2020",
"images": [
{"fileName":"c","id":"3","createDate":"2-1-2020"}
]}
Current Code that just selects without grouping LINQ(vb.net):
Dim imageResult = (From p In db.file_images Where p.user_id = userIdParam).ToList()
For each p in imageResult
mImageList.Add(New mImage With {.id = p.image_id, .description = p.image_desc, .fileName = p.image_file, .createDate= p.create_timestamp})
Next
I can't sort out how to select into groups. The for..each is required because some other stuff goes on before the item is added to the list.
The syntax i have (not working, can't work out the select into):
Dim imageResultGroup = (From p in db.file_images where p.user_id = userIDParam).GroupBy(Function(g) g.create_timestamp).Select(Function(grp) New mImageParent with {.groupDate = grp.Key, images = grp.ToList()})

The following method will return an anonymous object that has the following properties:
createdDate - the grouped on date
images - a collection of mImage
VB.Net Code:
Dim groupedImages =
From fileImage As mImage In fileImages
Select fileImage
Group By createdDate = fileImage.createDate
Into images = Group
Order By createdDate
With a little refactoring, you can rename the createdDate property to groupDate.

Related

Hibernate createNativeQuery returns duplicate rows

I have 2 database tables Customer and Items with 1 -> many relation. To fetch data from database i am using the following query.
select customer.id, customer.name, items.itemName, items.itemPrice from testdb.customer INNER JOIN items ON items.customer_Id = customer.id
I have an entity class Customers
#Entity
public class Customer{
#Id
private int id;
#Column
private String name;
#Column
private String itemName;
#Column
private int itemPrice;
public Customer() {}
//Getter and setter are here
.......
}
in Service class i have the following code.
#GET #Path("/getCustomerInfo")
#Produces(MediaType.APPLICATION_JSON)
public List getCustomerInfo() {
CustomerDao dao = new CustomerDao();
return dao.getBuildingsCustomerInfo();
}
in my DAO class i have the following code
public List<Customer> getCustomerInfo(){
Session session = SessionUtil.getSession();
String queryString = "the above mentioned query";
List<Customer> customerInfo = session.createNativeQuery(queryString, Customer.class) ;
session.close();
return customerInfo;
}
I am getting the following JSON response from the service
[id:1, name:"Alfred", itemName:"jeans", itemprice:10],[id:1, name:"Alfred", itemName:"jeans", itemprice:10],[id:2, name:"James", itemName:"watch", itemPrice:20 ],[id:2, name:"James", itemName:"watch", itemPrice:20 ], [id:2, name:"James", itemName:"watch", itemPrice:20 ]
The number of results are 5 which is correct But 2nd result is a copy of 1st, 4th and 5th are copies of 3rd. In 2nd, 4th and 5th results the itemName and the itemPrice should be different.
if I use createSQLQuery(queryString); instead of createNativeQuery(queryString, Customer.class); I am getting the correct result but without entity attribut names.
[1, "Alfred", "jeans", 10],[1, "Alfred", "shirt", 15],[2, "James", "watch", 20], [2, "James", "coffee", 25], [2, "James", "drinks", 30]
I have seen number of articles but could not find the solution. I have to use createNativeQuery() not createSQLQuery() because I need to map the entity class attributes. Please let me know if i am doing something wrong.
Your data structure is wrong on the Java side and not corresponding to the database relation. In the relation you describe you need to have a list of items:
#Entity
public class Customer implements Serializable {
// ... the fields you have so far
// assuming the parent field on the other side is called customer
// you may also want to set the cascade and orphanRemoval properties of the annotation
#OneToMany(mappedBy = "customer")
#JsonManagedReference // assuming you're using Jackson databind JSON
private List<Item> items;
}
And on the Item side:
#Entity
public class Item implements Serializable {
#Id
private int id;
#JsonBackReference
#ManyToOne
#JoinColumn(name = "customer_Id")
private Customer customer;
}
Then if you really the JSON data strucutred that way, you need a third Entity class to use as a ResultSetMapping.
#Entity
#SqlResultSetMapping(
name = "CustomerItem",
entities = #EntityResult(entityClass = CustomerItem.class)
)
#NamedNativeQueries({
#NamedNativeQuery(
name = "CustomerItem.getAll",
resultSetMapping = "CustomerItem"
query = "select customer.id as cid, items.id as iid, customer.name,"
+ " items.itemName, items.itemPrice from testdb.customer INNER JOIN"
+ " items ON items.customer_Id = customer.id"
)
})
public class CustomerItem implements Serializable {
#Id
private int cid;
#Id
private int iid;
#Column
private String name;
#Column
private String itemName;
#Column
private int itemPrice;
... getters and setters
}
Then you can use the native query in named variant, which should offer some slight optimizations.
List<CustomerItem> lst = em.createNamedQuery("CustomerItem.getAll", CustomerItem.class)
.getResultList();
The use of #SqlResultSetMapping is so that the returned entities are not monitored for changes, but you can still use the defined entity for the result. I believe that by JPA specification it should also work without it, but in Hibernate it doesn't. Could be a bug, or a planned, but not implemented feature, or I could just be misinterpreting the JPA usage, but this workaround does work with Hibernate 5+.
Not sure about the exact reason behind duplicates but SELECT DISTINCT will solve your issue as it will take only distinct records.
Refer using-distinct-in-jpa
I solve this issue by using #SqlResultSetMapping

Propagate DataMember to Sub Class

I have two serializable classes of which the first, Main, includes members Id, and Details, an enumeration of the second class, Detail.
Eg
<DataContract()>
Class [Main]
<DataMember(Name:="id")>
Property [Id] As Integer = 0
<DataMember(Name:="details")>
Property [Details] As IEnumerable(Of [Detail]) = Nothing
End Class
<DataContract()>
Class [Detail]
<DataMember(Name:="name")>
Property [Name] As String = Nothing
<DataMember(Name:="dob")>
Property [BirthDate] As Date? = Nothing
End Class
(This is a very simplified example so please don't ask why I want to do this.)
What I want to end up with is just, Details, the collection of Detail, BUT with the Id property from the parent, Main, included.
So ...
Id = 1, Name = "John Smith", BirthDate = #1/1/1990#
Id = 1, Name = "Jane Jones", BirthDate = #2/2/1990#
Id = 2, Name = "Jim Hicks", BirthDate = #3/3/1990#
Id = 3, Name = "Jana Walsh", BirthDate = #4/4/1990#
Id = 3, Name = "Jason Brown", BirthDate = #5/5/1990#
Now, I know I could simply iterate through the results and copy Id from the Main object to the Detail objects. But is there a way of adding Id to Detail objects via the serialization process? (Sorry if I have some nomenclature wrong here re serialization, etc.)
Note: I can't - or don't want to - make Detail a child class of Main because Detail is re-used in other classes.

Create an dyanamic list from a List(of Class) with where condition

I have a class named UserDetail. I have Userstatus field in the userdetail class and created a List(Of UserDetail).
Dim UserList As New List(Of UserDetail)()
UserList.Add(New UserDetail() With {.UserId = 1, .UserName = 'ABC', .Status= 0 })
UserList.Add(New UserDetail() With {.UserId = 2, .UserName = 'CFC', .Status= 2 })
UserList.Add(New UserDetail() With {.UserId = 3, .UserName = 'AAC', .Status= 2 })
I want to iterate all the userdetail from the List and get all with status = 1 to a new list wihch contains only UserID.
How can i do this with Minimum steps..
You can use linq to apply the filter using .Where and get list of UserId using .Select
C# syntax
var result = UserList.Where(u=>u.status == 1).Select(u=>u.UserId);
VB syntax
Dim result = From user In UserList
Where UserList.status = 1
Select user.UserId
This MSDN article Introduction to LINQ in Visual Basic will help you learn LinQ using VB.net
You can use LINQ to iterate your list of users:
For Each user As var In UserList.Where(Function(u) u.Status = 1)
...
Next

Group By Sum Linq to SQL in C#

Really stuck with Linq to SQL grouping and summing, have searched everywhere but I don't understand enough to apply other solutions to my own.
I have a view in my database called view_ProjectTimeSummary, this has the following fields:
string_UserDescription
string_ProjectDescription
datetime_Date
double_Hours
I have a method which accepts a to and from date parameter and first creates this List<>:
List<view_UserTimeSummary> view_UserTimeSummaryToReturn =
(from linqtable_UserTimeSummaryView
in datacontext_UserTimeSummary.GetTable<view_UserTimeSummary>()
where linqtable_UserTimeSummaryView.datetime_Week <= datetime_To
&& linqtable_UserTimeSummaryView.datetime_Week >= datetime_From
select linqtable_UserTimeSummaryView).ToList<view_UserTimeSummary>();
Before returning the List (to be used as a datasource for a datagridview) I filter the string_UserDescription field using a parameter of the same name:
if (string_UserDescription != "")
{
view_UserTimeSummaryToReturn =
(from c in view_UserTimeSummaryToReturn
where c.string_UserDescription == string_UserDescription
select c).ToList<view_UserTimeSummary>();
}
return view_UserTimeSummaryToReturn;
How do I manipulate the resulting List<> to show the sum of the field double_Hours for that user and project between the to and from date parameters (and not separate entries for each date)?
e.g. a List<> with the following fields:
string_UserDescription
string_ProjectDescription
double_SumOfHoursBetweenToAndFromDate
Am I right that this would mean I would have to return a different type of List<> (since it has less fields than the view_UserTimeSummary)?
I have read that to get the sum it's something like 'group / by / into b' but don't understand how this syntax works from looking at other solutions... Can someone please help me?
Thanks
Steve
Start out by defining a class to hold the result:
public class GroupedRow
{
public string UserDescription {get;set;}
public string ProjectDescription {get;set;}
public double SumOfHoursBetweenToAndFromDate {get;set;}
}
Since you've already applied filtering, the only thing left to do is group.
List<GroupedRow> result =
(
from row in source
group row by new { row.UserDescription, row.ProjectDescription } into g
select new GroupedRow()
{
UserDescription = g.Key.UserDescription,
ProjectDescription = g.Key.ProjectDescription,
SumOfHoursBetweenToAndFromDate = g.Sum(x => x.Hours)
}
).ToList();
(or the other syntax)
List<GroupedRow> result = source
.GroupBy(row => new {row.UserDescription, row.ProjectDescription })
.Select(g => new GroupedRow()
{
UserDescription = g.Key.UserDescription,
ProjectDescription = g.Key.ProjectDescription,
SumOfHoursBetweenToAndFromDate = g.Sum(x => x.Hours)
})
.ToList();

JasperReports for grails: Using HashMap as Model?

Imagine I have two classes in Groovy that look like that:
class Person {
int id;
String name;
}
class Item {
int id;
int price;
}
Now it would be simple to create a JasperReport listing all persons' names using the following SQL:
SELECT name FROM Person
Also, it would be easy to pass a Model from which the list should be created:
def p = Person.withCriteria {
eq('name','SomeGuy')
}
chain(controller:'jasper',action:'index',model:[data:p],params:params)
But what I want to do is to use the following query:
SELECT name, (SELECT sum(i.price) FROM Item f WHERE f.id=p.id) as priceSum FROM Person p
And now this is the part where I don't know how to go on: How can I pass any Model to the jasperReport? I can't just use
def p = Person.withCriteria {
eq('name','SomeGuy')
}
because then, the priceSum attribute would be missing.
What I would like to do is something like this:
def l = ['name':'SomeGuy','priceSum':'5000']
chain(controller:'jasper',action:'index',model:[data:l],params:params)
But this doesn't work either, it gives me:
Message: Cannot get property 'name' on null object
Caused by: java.lang.NullPointerException: Cannot get property 'name' on null object
Is there anything simliar to this that would work?