[英]Entity Framework generated sql restrict related records
我有以下linq选择查询循环所有链接到'adrianMember'的'Places'以B开头,我只想显示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限制为类似的东西
SELECT PlaceName FROM Places WHERE MemberId = 1 AND PlaceName like'B%'
我在我的项目中有几种情况,上面生成的sql会使查询太慢(每个成员超过20列有20,000条记录)。 如果我有更多记录,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查询来检索每个相应的Place记录,并且重要的是,将项目列为我想要的列(仅描述)并限制行(以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 to Entities的严格控制位。
这将进入数据库一次,只检索我想要的成员和项目,并限制两个表和所有在一个可爱的高效查看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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.