C# 实体框架生成的sql限制相关记录

C# 实体框架生成的sql限制相关记录,c#,.net,entity-framework,C#,.net,Entity Framework,我有下面的linq select查询,它在链接到以B开头的“adrianMember”的所有“place”周围循环,我只想显示PlaceName。我有一个导航协会从一个成员到另一个地方,但不是从一个地方到另一个成员 using (var fdb = new FALDbContext()) { var adrianMember = fdb.Members.Find(1); foreach (string s in adrianMember.Places.Where(p=>p

我有下面的linq select查询,它在链接到以B开头的“adrianMember”的所有“place”周围循环,我只想显示PlaceName。我有一个导航协会从一个成员到另一个地方,但不是从一个地方到另一个成员

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);
    }
}
我也尝试过各种linq语法,例如不使用Find

var adrianMember = fdb.Members.Where(m => m.MemberId == 1).FirstOrDefault();
并提供两个linq查询,一个用于检索成员,然后稍后检索相关位置(希望让EF执行一些延迟加载),但这仍然会导致非常低效的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);
        }
    }
}
SQL输出获取所有行和列

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
有没有办法将sql限制为

从MemberId=1和PlaceName(如“B%”)中选择PlaceName

在我的项目中,有几种情况下,上面生成的sql会使查询速度太慢(每个成员20列上有20000条记录)。如果我有更多的记录,linq是否足够聪明来进行更改?

试试这个:

using (var fdb = new FALDbContext()) 
{     
    var members = fdb.Members.Where(m=>m.FirstName == "Bob");      
    foreach (var member in members)     
    {         
        fdb.Places.Where(p => p.PlaceName.StartsWith("B") && p.MemberId == member.Id).Select(p => p.PlaceName);
        foreach (var place in places)         
        {             
            Console.WriteLine(place);         
        }     
    } 
} 

还有一个类似的问题

在远离这个问题一个月后,我想我应该再看一看

首先,我真的不确定我想要实现什么!!!然而,我似乎已经找到了一些有趣的、更高效的sql查询来满足我的需求

我的第一个选择是使用Entry和Collection方法使用显式加载。这将创建一个SQL查询来检索每个对应的位置记录,重要的是,它会投影我想要的列(只是描述)并限制行(那些以L开头的位置)。如果我有很多相关的位置,这确实会创建很多查询,但是如果我不知道要检索哪些位置,我可以动态地进行查询

    using (var fdb = new FALDbContext())
    {
        foreach (var member in fdb.Members)
        {
            var places = fdb.Entry(member)
                            .Collection(m => m.Places)
                            .Query()
                            .Where(p => p.PlaceName.StartsWith("L"))
                            .Select(p => p.PlaceName);

            foreach (var place in places)
            {
                Console.WriteLine(place);
            }
        }
    }
第二个选项是使用延迟加载,但要为实体指定严格控制的LINQ位

这将进入数据库一次,只检索我想要的成员和项目,并限制这两个表和一个看起来非常高效的sql查询

    using (var fdb = new FALDbContext())
    {
        var myList = fdb.Members
                            .Where(m => m.GenderShareWithId > 0)
                            .Select(m => new { m.MemberId, m.DisplayName, Places = m.Places.Where(p => p.PlaceName.StartsWith("L")).Select(p => p.PlaceName) });

        foreach (var item in myList)
        {
            Console.WriteLine(item.DisplayName);
            foreach (var place in item.Places)
            {
                Console.WriteLine(" - " + place);
            }
        }
    }


SELECT 
    [Extent1].[MemberId] AS [MemberId], 
    [Extent1].[DisplayName] AS [DisplayName], 
    [Extent2].[PlaceName] AS [PlaceName]
FROM  [dbo].[Members] AS [Extent1]
LEFT OUTER JOIN [dbo].[Places] AS [Extent2] 
    ON ([Extent1].[MemberId] = [Extent2].[Member_MemberId]) AND ([Extent2].[PlaceName] LIKE N'L%')
WHERE [Extent1].[GenderShareWithId] > 0

除此之外,我发现可以删除virtual关键字来关闭延迟加载。然后,显式加载相关条目并应用过滤器(有效地附加记录)。然而,如果上面的程序能够自动地像那样工作,那就太好了。如果有人有任何意见,我想听听。只有指定了FirstOrDefault,这才有效。当指定FirstOrDefault时,发送到sql server的sql查询不受限制,因此不幸的是,这仍然不会导致非常高效的查询。我的错误,请参阅我答案中的修订代码部分,而不是going member。我从fdb中选择的位置。位置,这会生成您想要的sql mm,是的,如果…(抱歉,Tommy)这会起作用…我有一个从一个地方到另一个成员的导航协会,但我没有。因此,“p.Member.Id==Member.Id”不会编译。(感谢您的关注)还有其他建议或想法吗?最后一次尝试:),编辑了我的示例以不使用导航关联。