jiy
jiy

Reputation: 868

How to pass (and return) LINQ IQueryable<T> to a Function?

I'd like the ability to pass (and return) an IQueryable<T> to a function for adding expression logic:

public void getShips()
{
    var shipyard =
        from ship in db.Ships
        select new { ship };

    var ballerShips = GetExpensiveShips(shipyard);     
}

public IQueryable<T> GetExpensiveShips<T>(IQueryable<T> query)
{
    return query.Where(q => q.NetValue > 150000); // <== Error CS1061
}

Returns this error:

Error   CS1061  'T' does not contain a definition for 'NetValue' and no
extension method 'NetValue' accepting a first argument of type 'T' could be 
found (are you missing a using directive or an assembly reference?

I've tried defining an Interface for shipyard and adding where T : IShipyard but that seems to cause more problems and leads to substantial boilerplate.

I would also like to avoid executing the SQL till after passing through my function.

Is this possible?

Upvotes: 1

Views: 2010

Answers (2)

Joe White
Joe White

Reputation: 97768

You need to remove some unnecessary complexity.

Change the last line of your query to:

select ship;

And then change your method declaration to:

public IQueryable<Ship> GetExpensiveShips(IQueryable<Ship> query)

Your method is already written so that it will only work on Ship instances - it uses the Ship.NetValue property. So, you need to be explicit that that's the type it should take. There's no need for this method to be generic.

Upvotes: 4

Backs
Backs

Reputation: 24913

You need something, that contains NetValue property. T is generic type without properties. So, adding an interface is right way:

interface IShip
{
    int NetValue {get;}
}

class Ship : IShip
{
    public int NetValue {get;set;}
}

public IQueryable<T> GetExpensiveShips<T>(IQueryable<T> query)
    where T : IShip, class
{
    return query.Where(q => q.NetValue > 150000);
}

Upvotes: 2

Related Questions