views:

4544

answers:

5

Hi, I am having problems querying many-to-many relationships in Linq To Entities. I am basically trying to replicate this query using Linq:

Select * 
FROM Customer 
LEFT JOIN CustomerInterest ON Customer.CustomerID = CustomerInterest.CustomerID
LEFT JOIN Interest ON CustomerInterest.InterestID = Interest.InterestID
WHERE Interest.InterestName = 'Football'

I have looked around the net and not really found any suitable examples of how to do this. The closest I have got is:

List<Customer> _Customers = (from _LCustomers in _CRM.Customer.Include("CustomerInterest.Interest")
                                  where _LCustomers.CustomerInterest.Any(x => x.Interest.InterestName == "Football")
                                  select _LCustomers).ToList();

The problem with this is that if a customer has more than one interest and one of them is "Football" then all of them are returned. I have also looked at All() which has the inverse problem, i.e. will only return if they have one interest and it is football, if they have two and one of them isn't football nothing is returned.

Anyone got any ideas?

+1  A: 

I am not sure what you want to obtain. A list of customers with a customer interest and a interest? Just start the query at customer interest.

context.CustomerInterest.
   Where(ci => ci.Interest.InterestName == "Football").
   Select(ci => new
   {
      Customer = ci.Customer,
      CustomerInterest = ci,
      Interest = ci.Interest
   });

But this is highly redudant. Why not just get the matching customer interests?

IEnumerable<CustomerInterest> customerInterests = context.CustomerInterest.
   Where(ci => ci.Interest.InterestName == "Football");

You can still access the other information without needing to store it explicitly.

foreach (CustomerInterest customerInterest in customerInterests)
{
   DoSomething(customerInterest);
   DoSomething(customerInterest.Customer);
   DoSomething(customerInterest.Interest);
}
Daniel Brückner
well the idea is to return a customer with all related data using the customer as the base of the query with a single db hit.The data returned will be serialized and returned to the client (for a customer maintenance screen) in single wcf call.As we are trying to keep the client slim and as generic as possible the client has no concept of the entities in the edmx, it just works with the deserialized xml and works with that.I am trying to avoid the anonymous types and return a Customer object with only the related data that matches the where clause.
JD
+1  A: 

If you trying to keep it generic, better way is to go with entity sql[Esql]. Coz L2E doesn't support where for collections in linq query.

You cannot use

customer.Interests.Where(interest => interest.Name =='FootBall')

The query would look like this..

context.CreateQuery(@"SELECT VALUE Customer FROM Customer WHERE EXISTS( SELECT VALUE FROM CustomerInterest WHERE CustomerInterest.Ineterest.Name = 'FootBall')).Include("Interest");

hope it helps!

Deepak N
Doesn't dropping to esql for solutions just feel like a hack though? You lose all your intellisense and just about everything that was supposed to be the point of using EF. Might as well execute it in a DbReader at that point.
Jason Short
Yeah.. but you get a typed Entity Customer in EF compared to Data Records returned by DbReader in ADO.
Deepak N
A: 

That's to much for LINQT. Try use a view at your database or work as Deepak N said. Best

Eduardo Xavier
+1  A: 

Try this,

var result = from c in ctx.Customer
             from i in c.Interest
             where i.InterestName == "Football"
             select c;

Hope this helps,

Ray.

ray247
A: 
        var results = from c in _CRM.Customer
                      from ci in c.Interests
                      join i in _CRM.Interests
                      on ci.ID equals i.ID
                      where i.Interest = "Football"
                      select c;
CkH