views:

45

answers:

1

I am just learning Linq and ran into a problem. For some validation, I am getting the last odometer reading from our database and need to compare that to the next reading. The odometer reading is an int on the incoming data and double on the database (changed to int on the dbml file).

Below is my code:

private bool IsValidOdometer(string equipment, int odometerReading)
{
    bool returnVariable = true;
    CarteGraphDataDataContext db = new CarteGraphDataDataContext();

    var odometer = (from p in db.EquipmentMainGenerals join q in db.EquipmentFuelLogs 
            on p.wdEquipmentMainGeneralOID equals q.wdEquipmentMainGeneralOID
            where p.VehicleId == equipment
            orderby q.Odometer descending
            select q.Odometer).Take(1);

    int previousOdometer = odometer;

    if (odometer.Count() != 0)
    {
        if (odometerReading < previousOdometer)
        {
            returnVariable = false;
        }
    }

    return returnVariable;
}

The problem line is int previousOdometer = odometer;. The error I get is:

Cannot implicitly convert type 'System.Linq.IQueryable' to 'int'

How do I fix this?

+4  A: 

Instead of Enumerable.Take use Enumerable.Single. Enumerable.Take will return an IEnumerable but Enumerable.Single will return a single instance (or throw):

int odometer = (from p in db.EquipmentMainGenerals
                join q in db.EquipmentFuelLogs 
                on p.wdEquipmentMainGeneralOID
                    equals q.wdEquipmentMainGeneralOID
                where p.VehicleId == equipment
                orderby q.Odometer descending
                select q.Odometer).Single();

int previousOdometer = odometer;

Also, I would explicitly type odometer here instead of implicitly as you've done.

Lastly your line

CarteGraphDataDataContext db = new CarteGraphDataDataContext();

should really be in using block like so

using(CarteGraphDataDataContext db = new CarteGraphDataDataContext()) {
    // okay to go
}
Jason
Thank you. The only thing to add is that I had to cast it to int.
Mike Wills
@Mike Wills: Ah, what's the type in the database and what's the type of `EquipmentFuelLogs.Odometer`?
Jason
I think he probably wants to use First() instead of Single() since Single ensures that there was only one item in the IEnumerable. In this case he wants the newest one
Mike
@Mike I may not always have a row returned (new vehicle in my case). Would FirstOrDefault() handle that?
Mike Wills
@Mike It depends on how you handle it. I think for ints FirstOrDefault() will return 0 as a default. You might want to stick with First() and handle the exception if you want to know that there wasn't a previous entry
Mike
If you are going have one or none returned use `SingleOrDefault`. For a new vehicle I would presume the `odometer` should be zero which is what `SingleOrDefault` will return to you.
Jason