簡體   English   中英

實體框架生成了sql限制相關記錄

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM