Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a where clause on a linq join (lambda)?

I have two database tables Contact (Id, Name, ...) and ContactOperationalPlaces (ContactId, MunicipalityId), where a contact can be connected to several ContactOperationalPlaces.

What I'm trying to do is to build a query (ASP .NET, C#) with IQueryable, that only selects all the contacts that exists in the ContactOperationalPlaces table, with a given MunicipalityId.

The sql query looks like this:

select * from Contacts c 
right join ContactOperationPlaces cop on c.Id = cop.ContactId 
where cop.MunicipalityId = 301;

With linq it would look something like this:

//_ctx is the context
var tmp = (from c in _ctx.Contacts
             join cop in _ctx.ContactOperationPlaces on c.Id equals cop.ContactId
             where cop.MunicipalityId == 301
             select c);

So, I know how to do this if the point was to select all of this at once, unfortunately it's not. I'm building a query based on user input, so I don't know all of the selection at once.

So this is what my code looks like:

IQueryable<Contacts> query = (from c in _ctx.Contacts select c);
//Some other logic....
/*Gets a partial name (string nameStr), and filters the contacts 
 so that only those with a match on names are selected*/
query = query.Where(c => c.Name.Contains(nameStr);
//Some more logic
//Gets the municipalityId and wants to filter on it! :( how to?
query = query.where(c => c.ContactOperationalPlaces ...........?);

The difference with the two where statements is that with the first one, each contact has only one name, but with the latter a contact can contain several operational places...

I have managed to find one solution, but this solution gives me an unidentyfied object, that contains both of the tables. And I don't know how to proceed with it.

query.Join(_ctx.ContactOperationPlaces, c => c.Id, cop => cop.ContactId,
      (c, cop) => new {c, cop}).Where(o => o.cop.municipalityId == 301);

The object returned from this expression is System.Linq.Iqueryable<{c:Contact, cop:ContactOperationalPlace}>, and it can't be cast to Contacts...

So, that's the issue. The answer is probably pretty simple, but I just can't find it...

like image 919
linnkb Avatar asked Dec 16 '11 08:12

linnkb


People also ask

How add join in LINQ?

If you want to be able to get this information outside the query, use the . Include("Navigational Propertyname") command to add your 'Joins' which will result in adding the respective objects or list of objects to the query result.

Can we use joins in LINQ?

Joins on object collections vs. In a LINQ query expression, join operations are performed on object collections. Object collections cannot be "joined" in exactly the same way as two relational tables.


2 Answers

You create an anonymous type with both objects before your where clause and filter it on ContactOperationPlaces value. You just have to select the Contact after that.

query.Join(_ctx.ContactOperationPlaces, c => c.Id, cop => cop.ContactId,
           (c, cop) => new {c, cop}).Where(o => o.cop.municipalityId == 301)
                                    .Select(o => o.c)
                                    .Distinct();
like image 155
Ufuk Hacıoğulları Avatar answered Nov 04 '22 18:11

Ufuk Hacıoğulları


You don't need to return new objects in the result selector function. The delegate provides both variables so you can choose one or the other, or some other variation (which would require a new object). Try this:

query.Join(_ctx.ContactOperationPlaces, c => c.Id, cop => cop.ContactId,
  (c, cop) => c).Where(o => o.cop.municipalityId == 301);
like image 40
Michael Yoon Avatar answered Nov 04 '22 20:11

Michael Yoon