c# - ईएफ: "चुनें" प्रक्षेपण के साथ एक आवरण वस्तु बनाने के दौरान, "शामिल करें" नेविगेशन प्रॉपर्टी



entity-framework linq-to-sql (1)

मैं Include साथ मेरी क्वेरी में नेविगेशन प्रॉपर्टी भी Include हूं, ताकि बाद में आलसी लोड नहीं किया जा सके। लेकिन यह काम नहीं करता है, जब मैं प्रोजेक्शन Select साथ एक अनाम आवरण-वस्तु बना देता हूं

मुझे सरल उदाहरण दिखाएं। इकाई :

public class UserEntity {
    public string Name {get;set;}
    public virtual ICollection<UserEntity> Friends { get; set; }
}

क्वेरी :

var entry = _dbCtx
    .Users
    .Include(x => x.Friends)
    // Select here is simplified, but it shows the wrapping
    .Select(user => new {
        User = user
    })
    .First();

// Here we have additional lazy loaded DB call
var friends = entry.User.Friends.Select(x => x.Name).ToList();

और मैं भी उत्पन्न एसक्यूएल से देखता हूं, नेविगेशन प्रॉपर्टी शामिल नहीं है:

SELECT 
    [Limit1].[Name] AS [Name], 
    FROM ( SELECT TOP (1) 
        [Extent1].[Name] AS [Name]
        FROM [dbo].[Users] AS [Extent1]
    )  AS [Limit1]

क्या इस मामले में Friends नेविगेशन संपत्ति को Include करना संभव है, ताकि User आलसी लोड किए बिना डेटा प्राप्त कर सके?

मुझे यह भी काम करने की उम्मीद थी:

var entry = _dbCtx
    .Users
    .Select(user => new {
        User = user
    })
    .Include(x => x.User.Friends)
    .First();

लेकिन अपवाद प्राप्त करना:

अमान्यऑपरेशन अपवाद: क्वेरी का नतीजा प्रकार न तो एक इकाई प्रकार के साथ एक EntityType और न ही एक संग्रह प्रकार है इनमें से किसी एक परिणाम प्रकार के साथ एक क्वेरी शामिल करने के लिए पथ शामिल किया जा सकता है।

मेरे पास आने वाले कुछ काम करनेवाले हैं, लेकिन वे किसी तरह मुश्किल हैं:

  1. Select में हमारे गुमनाम वस्तु को अतिरिक्त संपत्ति जोड़ें:

    var entry = _dbCtx
        .Users
        .Select(user => new {
            User = user,
            UsersFriends = user.Friends
        })
        .First();
    
    // manually copy the navigation property
    entry.User.Friends = user.UsersFriends;
    
    // Now we don't have any addition queries
    var friends = entry.User.Friends.Select(x => x.Name).ToList();
  2. डीबी स्तर पर एक बेनामी ऑब्जेक्ट के लिए उपयोगकर्ता को नक्शा भी करें, और फिर सी # में UserEntity गुणों को मैप करें।

    var entry = _dbCtx
        .Users
        .Select(user => new {
            User = new {
                Name = user.Name,
                Friends = user.Friends
            }
        })
        .Take(1)
        // Fetch the DB
        .ToList()
        .Select(x => new {
            User = new UserEntity {
                Name = x.Name,
                Friends = x.Friends
            }
        })
        .First();
    
    // Now we don't have any addition queries
    var friends = entry.User.Friends.Select(x => x.Name).ToList();

तो अब, Friends लिए एक LEFT OUTER JOIN , लेकिन दोनों कामकाज काफी अच्छे नहीं हैं:

1) अतिरिक्त गुण और प्रति एक साफ तरीका नहीं है।

2) मेरे UserEntity में बहुत अधिक अन्य गुण हैं I इसके अतिरिक्त, हर बार जब हम नए गुण जोड़ते हैं, तो हमें यहां चयनकर्ताओं को भी संशोधित करना चाहिए।

क्या पहला नमूना सहित नेविगेशन प्रॉपर्टी हासिल करने का कोई तरीका है?

पढ़ने के लिए धन्यवाद और मुझे उम्मीद है कि इस के लिए कोई सुराग है।

संपादित करें:

मैं एक वास्तविक उपयोग-केस दिखाने के लिए इकाई और क्वेरी का विस्तार करूँगा।

सत्ता

public class UserEntity {
    public string Name {get;set;}
    public int Score {get;set;}
    public virtual ICollection<UserEntity> Friends { get; set; }
}

पूछताछ

var entry = _dbCtx
    .Users
    .Include(x => x.Friends)
    .Select(user => new {
        User = user,
        Position = _dbCtx.Users.Count(y => y.Score > user.Score)
    })
    .First();

_why_ के रूप में कोई जवाब नहीं, लेकिन बेहतर कोड फ़ॉर्मेटिंग करना चाहिए ...

मैं वास्तव में हैरान हूँ कि इस तरह से काम करता है। शायद ईएफ पता लगा रहा है कि आप Friends प्रॉपर्टी सीधे आपके प्रक्षेपण में उपयोग नहीं कर रहे हैं और इस तरह इसे अनदेखा कर रहे हैं। क्या होगा यदि आप ईएफ क्वेरी के बाहर ऑब्जेक्ट (ए) समझाएंगे:

var entry = _dbCtx
    .Users
    .Include(x => x.Friends)
    .Take(1);  // replicate "First" inside the EF query to reduce traffic
    .AsEnumerable()  // shift to linq-to-objects
    // Select here is simplified, but it shows the wrapping
    .Select(user => new {
        User = user
    })
    .First()




entity-framework-6