linqbltoolkit

BLToolKit, Linq Query, SQL Not what I expected


I am using BLToolKit in a project of mine and I was trying to get this to work. What I don't like is that I am trying to average a bunch of temps down to the minute, but the select statement that is being generated groups by the minute but then selects the original time. I think I am doing the linq expression correctly (but then again, i am not getting the results i expect). (this is C#, if you care) Anyone know what is going wrong?

                 var test = (from r in db.SensorReadingRaws
                        where r.TimeLogged < DateTime.Now.AddMinutes(-2)
                        group r by new
                        {
                            Sensor = r.SensorNumber,
                            //group time down to the minute
                            Time = r.TimeLogged.AddSeconds(-1 * r.TimeLogged.Second).AddMilliseconds(-1 * r.TimeLogged.Millisecond)
                        } into grouped
                        select new SensorReading
                        {
                            SensorNumber = grouped.Key.Sensor,
                            TimeLogged = grouped.Key.Time,
                            Reading = (int)grouped.Average(x => x.Reading)
                        }).ToList();

            textBox1.Text = db.LastQuery;

and the resulting query is this

SELECT
[r].[SensorNumber],
[r].[TimeLogged],
Avg([r].[Reading]) as [c1]
FROM
[SensorReadingRaw] [r]
WHERE
[r].[TimeLogged] < @p1
GROUP BY
[r].[SensorNumber],
DateAdd(Millisecond, Convert(Float, -DatePart(Millisecond, [r].[TimeLogged])), DateAdd(Second, Convert(Float, -DatePart(Second, [r].[TimeLogged])), [r].[TimeLogged])),
[r].[TimeLogged]

Solution

  • I discovered that

    BLToolkit.Data.Linq.Sql.AsSql<T>(T obj)
    

    can be used as a workaround for this case.

    When applying this function to the required grouped key properties in select statement you get rid of grouping/selecting an original field.

    It may look something like:

    _queryStore.Leads().
        GroupBy(x => new {
            x.LeadDate.Hour,
            x.LeadDate.Minute
        }).
        Select(x => new {
            Hour = Sql.AsSql(x.Key.Hour),
            Minute = Sql.AsSql(x.Key.Minute),
            Count = x.Count()
        });
    

    and in your particular case:

                     var test = (from r in db.SensorReadingRaws
                            where r.TimeLogged < DateTime.Now.AddMinutes(-2)
                            group r by new
                            {
                                Sensor = r.SensorNumber,
                                //group time down to the minute
                                Time = r.TimeLogged.AddSeconds(-1 * r.TimeLogged.Second).AddMilliseconds(-1 * r.TimeLogged.Millisecond)
                            } into grouped
                            select new SensorReading
                            {
                                SensorNumber = grouped.Key.Sensor,
                                TimeLogged = Sql.AsSql(grouped.Key.Time),
                                Reading = (int)grouped.Average(x => x.Reading)
                            }).ToList();