linq multiple columns; getting weird results - linq

So m.SourceCollection has 1000 records going into this, which is a collection of items with a Lat and Lon property; nothing else. I run this:
var results = from locs in m.PlacesBeen
group locs by new {locs.Lat, locs.Lon }
into myGroup
select new { Lat = myGroup.Key.Lat, Lon = myGroup.Key.Lon };
The next breakpoint, "results" has three items in it. I'm just trying to do a group by and get the unique amounts out, much like I would in SQL.

That query looks OK - what results were you expecting?
Btw, here's a simpler way to write the same query:
var results =
m.PlacesBeen.Select (loc => new {locs.Lat, locs.Lon }).Distinct();

Related

How to make zero counts show in LINQ query when getting daily counts?

I have a database table with a datetime column and I simply want to count how many records per day going back 3 months. I am currently using this query:
var minDate = DateTime.Now.AddMonths(-3);
var stats = from t in TestStats
where t.Date > minDate
group t by EntityFunctions.TruncateTime(t.Date) into g
orderby g.Key
select new
{
date = g.Key,
count = g.Count()
};
That works fine, but the problem is that if there are no records for a day then that day is not in the results at all. For example:
3/21/2008 = 5
3/22/2008 = 2
3/24/2008 = 7
In that short example I want to make 3/23/2008 = 0. In the real query all zeros should show between 3 months ago and today.
Fabricating missing data is not straightforward in SQL. I would recommend getting the data that is in SQL, then joining it to an in-memory list of all relevant dates:
var stats = (from t in TestStats
where t.Date > minDate
group t by EntityFunctions.TruncateTime(t.Date) into g
orderby g.Key
select new
{
date = g.Key,
count = g.Count()
}).ToList(); // hydrate so we only query the DB once
var firstDate = stats.Min(s => s.date);
var lastDate = stats.Max(s => s.date);
var allDates = Enumerable.Range(1,(lastDate - firstDate).Days)
.Select(i => firstDate.AddDays(i-1));
stats = (from d in allDates
join s in stats
on d equals s.date into dates
from ds in dates.DefaultIfEmpty()
select new {
date = d,
count = ds == null ? 0 : ds.count
}).ToList();
You could also get a list of dates not in the data and concatenate them.
I agree with #D Stanley's answer but want to throw an additional consideration into the mix. What are you doing with this data? Is it getting processed by the caller? Is it rendered in a UI? Is it getting transferred over a network?
Consider the size of the data. Why do you need to have the gaps filled in? If it is known to be returning over a network for instance, I'd advise against filling in the gaps. All you're doing is increasing the data size. This has to be serialised, transferred, then deserialised.
If you are going to loop the data to render in a UI, then why do you need the gaps? Why not implement the loop from min date to max date (like D Stanley's join) then place a default when no value is found.
If you ARE transferring over a network and you still NEED a single collection, consider applying D Stanley's resolution on the other side of the wire.
Just things to consider...

ParseQuery not taking into consideration Where clause WindowsPhone

I made a new query to select from Article Class with where clause for each item selected. However, it keeps getting the whole list every time although there are selected fields!
Here is my code:
ParseQuery<Article> query = new ParseQuery<Article>();
if (souCategorie.SelectedIndex >= 0)
{
query.WhereEqualTo("idSCategorie", listeSouCategorie.ElementAt(souCategorie.SelectedIndex));
}
if(motcle.Text.Length > 0)
{
query.WhereContains("nom", motcle.Text);
// query.WhereContains("description", motcle.Text);
}
if(distance.Text.Length>0)
if (Convert.ToDouble(distance.Text) > 0)
{
Debug.WriteLine(distance.Text);
ParseGeoPoint geo = new ParseGeoPoint();
geo.Latitude = geoposition.Coordinate.Latitude;
geo.Longitude = geoposition.Coordinate.Longitude;
query.WhereWithinDistance("coordonnees", geo, ParseGeoDistance.FromKilometers(Convert.ToDouble(distance.Text)));
}
IEnumerable<Article> lst = await query.FindAsync();
rechercheResult.DataContext = lst.ToList();
What could possibly be wrong?
I know that queries can do funky stuff when you start trying to use GeoPoint stuff. I would try setting up two queries, one that just queries for objects within a distance, then pass that query into the second query that has the whereEqualTo and whereContains calls.

LINQ using Group with Count and Where, easy SQL, harder in LINQ

I'm trying to display cities names where a count is greater than 1. I can do it easy in SQL and am close in LINQ but can't figure out how to use group and also get a count and display a name
var query = (from c in Consumer
group c
by new { c.City, size = c.City.Count() }
into results
select new { Name = results.Key.City })
.Where(a => size > 0);
The size part doesn't work
try this query:
var list= Consumer.GroupBy(s=>s.City)
.Select(s=>new {
City = s.Key,
size = s.Count(),
})
.Where(s=>s.size>0).ToList();

How to query and calculate dates in the where clause of a LINQ statement?

I am having trouble with the following piece of code. Before I paste it, Let me give a bit of history on what should happen.
I have a model containing 2 fields of interest at the moment, which is the name of the order the customer placed, and the date at which he/she placed it. A pre-calculated date will be used to query the dateplaced field (and should only query the dates , and not the time). The query counts the amount of duplicates that occur in the MondayOrder field, and groups them together. Now , when I exclude the where clause which should query the dates, the query runs great. However, The goal of this query is to count the amount of orders for the following week based on the date the order has been placed.
List<string> returnlist = new List<string>();
DateTime dt = getNextWeekMondaysDate().Date;
switch (day)
{
case DayOfWeek.Monday:
{
var CountOrders =
from x in Data.EntityDB.Orders
group x by x.MondayOrder into m
let count = m.Count()
select new
{
MondayOrderItem = m.Key, Amount = count
};
foreach (var item in CountOrders)
{
returnlist.Add(item.MondayOrderItem + " : " +
item.Amount);
}
}
break;
The getNextWeekMondaysDate() method has an overload which I can use, where if I supply it a date, it will get the following Monday's date from the parameter given. The problem is though, LINQ does not accept queries such as the following:
var CountOrders =
from x in Data.EntityDB.Orders
where getNextWeekMondaysDate(x.DatePlaced.Value).Date == dt
group x by x.MondayOrder into m
let count = m.Count()
select new { MondayOrderItem = m.Key, Amount = count };
This is exactly what I must achieve. Is there any workaround for this situation?
UPDATE
Here is the exception I get when I try the 2nd query.
LINQ to Entities does not recognize the method 'System.DateTime getNextWeekMondaysDate(System.DateTime)' method, and this method cannot be translated into a store expression.
You cannot do this directly, as user-defined method calls cannot be translated to SQL by the EF query provider. The provider recognizes a limited set of .NET methods that can be translated to SQL and also a number of canonical functions as well. Anything that cannot be expressed using these methods only is off-limits unless you write your own query provider (which is only theoretically an option).
As a practical workaround, you can calculate an appropriate range for x.DatePlaced.Value in code before the query and then use specific DateTime values on the where clause.
As an intellectual exercise, note that this method is recognized by the query provider and can be used as part of the expression. So this abomination should work too:
var CountOrders =
from x in Data.EntityDB.Orders
where EntityFunctions.AddDays(
x.DatePlaced.Date.Value,
(9 - DateAndTime.DatePart(DateInterval.WeekDay, x.DatePlaced.Value)) % 7)
.Date == dt
group x by x.MondayOrder into m
let count = m.Count()
select new { MondayOrderItem = m.Key, Amount = count };
Linq to Entities doesn't know how to convert arbitrary C# methods into SQL - it's not possible in general.
So, you have to work with the methods it does understand.
In this case, you could do something like this:
DateTime weekBegin = CalculateWeekBegin( dt );
DateTime weekEnd = CalculateWeekEnd( dt );
var CountOrders =
from x in Data.EntityDB.Orders
where x.DatePlaced.Value >= weekBegin && x.DatePlaced.Value < weekEnd
group x by x.MondayOrder into m
let count = m.Count()
select new { MondayOrderItem = m.Key, Amount = count });

Linq query, how to build nested objects from single table

I have a single table and I need to build a bunch of nested objects based on the single table.
Data:
PointA PointB Month Time Price
1 2 11 11:00 10.99
1 2 12 11:00 9.99
Objects are
POINTS {PointA, PointB, Details}
Details {Month, ExtraDetails}
ExtraDetails {Time, Price}
I want to avoid having loads of loops and if statements, so should be able to use linq to do this. but its beyond my linq experience.
edit: These need grouping aswell
any help would be great.
Thanks
Just tried out a solution:
var nestedObjects = from row in data
select new {row.PointA, row.PointB, Details = new {
row.Month, ExtraDetails = new {
row.Time, row.Price
}
}};
This is assuming that you have already got your data into data.
Group by
If you want to group the Points together, you need 'Group By':
var nestedObjects = from row in data
group row by new { row.PointA, row.PointB } into Points
select new {
Points = Points.Key,
Details = from details in Points
select new { row.Month, ExtraDetails = new {
row.Time, row.Price
}}
};
A little more complicated - of course you might want to group by month as well, in which case, you need to follow the same pattern as for the Points bit. Note, this will not create tables, because the group by doesn't quite do that, but it at least creates the structure for you.
Assuming you got your classes defined for the objects you mentioned, and you have a constructor or properties so you can propery create the object in one line you could have a LINQ query returning a list of a POINTS.
If would go something lik this :
var res =
from item in table.AsEnumerable()
select new Points(){PointA = item["PointA"];
PointB = item["PointB"];
Details = from item2 in table.AsEnumberable()
where item["PointA"] = item2["PointA"] and item["PointB"] = item2["PointB"]
select new Details(){
month=item2["month"],
extraDetails = from item3 in table.AsEnumerable()...
}
};
At the end res will be a IEnumerable of Points
I am sorry for the code, I am not at a computer with .NET 3.5 so I cannot write a proper testable query

Resources