I have the following linq select query that loops round all the 'Places' linked to 'adrianMember' that start with B, I only want to show the PlaceName. I have a navigation association from Member to Place but not from Place to Member.
using (var fdb = new FALDbContext())
{
var adrianMember = fdb.Members.Find(1);
foreach (string s in adrianMember.Places.Where(p=>p.PlaceName.StartsWith("B")).Select(p => p.PlaceName))
{
Console.WriteLine("- " + s);
}
}
I have experimented with various linq syntax too, for example not using Find...
var adrianMember = fdb.Members.Where(m => m.MemberId == 1).FirstOrDefault();
and providing two linq queries, one to retrieve the member and then later retrieve the related places (and hopefully making the EF do some lazy deferred loading) but that still results in very inefficient sql.
using (var fdb = new FALDbContext())
{
//Need the FirstOrDefault otherwise we will return a collection (first or default will return the inner collection
//could have multiple members with multiple places
var members = fdb.Members.Where(m=>m.FirstName == "Bob");
foreach (var member in members)
{
var places = member.Places.Where(p => p.PlaceName.StartsWith("B")).Select(p => p.PlaceName);
foreach (var place in places)
{
Console.WriteLine(place);
}
}
}
The SQL output gets all rows and all columns
exec sp_executesql N'SELECT
[Extent1].[PlaceId] AS [PlaceId],
[Extent1].[PlaceName] AS [PlaceName],
[Extent1].[PlaceLocation] AS [PlaceLocation],
[Extent1].[Member_MemberId] AS [Member_MemberId]
FROM [dbo].[Places] AS [Extent1]
WHERE [Extent1].[Member_MemberId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=1
Is there a way to restrict the sql to something like
SELECT PlaceName FROM Places WHERE MemberId = 1 AND PlaceName like 'B%'
I have a couple of situations in my project where the above generated sql will make the query too slow (20,000 records per member over 20 columns). Is linq clever enough to make the change if I do have more records?