tags:

views:

190

answers:

2

I have a sp which builds a dynamic sql query based on my input params. I tried replicating in linq and somehow it seems incorrect.

My linq:

  var result = from R in db.Committees.Where(committeeWhere)
           join C in db.Employees.Where(employeeWhere) on R.PID equals C.PID
           join K in db.CommitteeTypes.Where(committeesWhere) on R.PID equals K.PID
           select new { R };

The 3 input params i have are: 1. Committee ID and/or

  1. Employee ID and/or

  2. Committee Type ID

Based on this, i want to be able to make the joins in my linq.

Note: i had to change table names and column names so please do not give thought on the names.

Sql snippet:

IF @committeeID is not null

set @wherestr = @wherestr + 'Committees.committeeID like' + @committeeID + @andstr

//...

IF  len(@wherestr) > 6      


  SELECT  @qrystr = @selectstr + @fromstr + left(@wherestr, len(@wherestr)-3) + ' ORDER BY Committees.committeeID DESC 

EXEC (@qrystr)
+1  A: 

Why do you need to use dynamic SQL? Wouldn't this work?

IQueryable<Committee> GetCommittees(int? committeeID, int? employeeID, int? committeeTypeID)
{
    var result = from R in db.Committees.Where(c => committeeID == null || committeeID == c.ID)
                 join C in db.Employees.Where(e => employeedID == null || employeeID == e.ID)
                   on R.PID equals C.PID
                 join K in db.CommitteeTypes.Where(c => committeeTypeID == null || committeeTypeID == c.ID)
                   on R.PID equals K.PID
                 select R;
}

If that won't work, you can use different predicate expressions depending on your parameters:

Expression<Func<Committee, bool>> committeeWhere;
if(committeeID.HasValue)
{
    int id = committeeID.Value;
    committeeWhere = c => c.ID == id;
}
else
{
    committeeWhere = c => true;
}
// etc

Update: Seeing your last comment, maybe you want something like this:

IQueryable<Committee> GetCommittees(int? committeeID, int? employeeID, int? committeeTypeID)
{
    var result = db.Committees.Select(c => c);

    if(committeeID.HasValue)
    {
        result = result.Where(c => c.ID = committeeID);
    }
    else if(employeeID.HasValue)
    {
        result = from R in result
                 join C in db.Employees.Where(e => employeeID == e.ID)
                   on R.PID equals C.PID
                 select R;
    }
    else if(committeeTypeID.HasValue)
    {
        result = from R in result
                 join K in db.CommitteeTypes.Where(ct => committeeTypeID == ct.ID)
                   on R.PID equals K.PID
                 select R;
    }

    return result;
}
dahlbyk
A: 

If I may improve upon dahlbyk's answer... sometimes joining introduces duplicates. If you really intend to filter - then filter. Also - if you add the relationships in the LinqToSql designer, you'll have properties (such as Committee.Employees) which will be translated for you.

IQueryable<Committee> GetCommittees(int? committeeID, int? employeeID, int? committeeTypeID){
    IQueryable<Committee> result = db.Committees.AsQueryable();
    if(committeeID.HasValue)
    {
        result = result.Where(c => c.ID = committeeID);
    }
    if(employeeID.HasValue)
    {
        result = result
            .Where(committee => committee.Employees
                .Any(e => employeeID == e.ID)
            );
    }
    if(committeeTypeID.HasValue)
    {
        result = result
            .Where(committee => committee.CommitteeTypes
                .Any(ct => committeeTypeID == ct.ID)
            );
    }
    return result;
}
David B
I just implemented what was requested. ;) You're right though, especially about the entity relationships. Joins in LINQ to SQL usually mean the model can be improved. Of course, the generated query will be different, which might be a consideration if you're using SQL CE which doesn't support subqueries.
dahlbyk
On a side note, I was deliberate in using Select(c => c) rather than AsQueryable(). The former hides the original source, eliminating the possibility that it will be used for anything other than this query (consistent with the other return values). AsQueryable() just returns the "full" Table<T> returned by db.Committees.http://community.bartdesmet.net/blogs/bart/archive/2008/08/20/what-do-vb-9-0-error-bc36593-expression-of-type-x-is-not-queryable-and-c-3-0-error-cs1936-could-not-find-an-implementation-of-the-query-pattern-for-source-type-x-really-mean.aspx
dahlbyk