एंटिटी फ्रेमवर्क मॉडल परिभाषाओं में वर्ग गुणों के लिए 'आभासी' का उपयोग क्यों करें?


223

निम्नलिखित ब्लॉग में: http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx

ब्लॉग में निम्नलिखित कोड नमूना है:

public class Dinner
{
   public int DinnerID { get; set; }
   public string Title { get; set; }
   public DateTime EventDate { get; set; }
   public string Address { get; set; }
   public string HostedBy { get; set; }
   public virtual ICollection<RSVP> RSVPs { get; set; }
}

public class RSVP
{
   public int RsvpID { get; set; }
   public int DinnerID { get; set; }
   public string AttendeeEmail { get; set; }
   public virtual Dinner Dinner { get; set; }
}

virtualएक वर्ग में एक संपत्ति को परिभाषित करते समय उपयोग करने का उद्देश्य क्या है ? इसका क्या प्रभाव पड़ता है?


9
क्या आप C # में 'वर्चुअल' कीवर्ड के सामान्य उद्देश्य को समझने के लिए कह रहे हैं या यह विशेष रूप से एंटिटी फ्रेमवर्क से कैसे संबंधित है?
एम। बैबॉक

2
@ M.Babcock: मैं पूछ रहा हूं कि इसका उद्देश्य क्या है क्योंकि यह गुणों से संबंधित है, क्योंकि मैंने ऐसा पहले कभी नहीं देखा है।
गैरी जोन्स 5

1
यदि आप इस बात से परिचित हैं कि वर्चुअल कीवर्ड विधियों में बहुरूपता को कैसे प्रभावित करता है तो यह गुणों के लिए समान है।
एम। बैबॉक

20
@ M.Babcock: मैं इसे और अधिक स्पष्ट कैसे कर सकता था? प्रश्न का शीर्षक है "कक्षाओं में गुणों के लिए 'आभासी' का उपयोग क्यों करें?"।
गैरी जोन्स

2
@ गैरी - गेटटर / सेटर गुण वास्तव में विधियों में संकलित हैं। इसलिए वे पारंपरिक क्लास फ़ील्ड जैसे 'पब्लिक वर्चुअल डिनर' नहीं हैं;
शान प्लॉर्ड

जवाबों:


248

यह इकाई ढांचे को आभासी संपत्ति के आसपास एक प्रॉक्सी बनाने की अनुमति देता है ताकि संपत्ति आलसी लोडिंग और अधिक कुशल परिवर्तन ट्रैकिंग का समर्थन कर सके। देखें कि वर्चुअल कीवर्ड का एंटिटी फ्रेमवर्क 4.1 POCO कोड में क्या प्रभाव हो सकता है? अधिक गहन चर्चा के लिए।

"चारों ओर एक प्रॉक्सी बनाएं" को स्पष्ट करने के लिए संपादित करें: "एक प्रॉक्सी बनाएं" के चारों ओर "मैं विशेष रूप से उल्लेख कर रहा हूं कि एंटिटी फ्रेमवर्क क्या करता है। इकाई ढांचे को आपके नेविगेशन गुणों को आभासी के रूप में चिह्नित करने की आवश्यकता है ताकि आलसी लोडिंग और कुशल परिवर्तन ट्रैकिंग का समर्थन किया जाए। POCO प्रॉक्सी बनाने के लिए आवश्यकताएँ देखें ।
एंटिटी फ्रेमवर्क इस कार्यक्षमता का समर्थन करने के लिए वंशानुक्रम का उपयोग करता है, यही कारण है कि यह आपके बेस क्लास POCOs में कुछ गुणों को आभासी चिह्नित करने की आवश्यकता है। यह सचमुच नए प्रकार बनाता है जो आपके POCO प्रकारों से प्राप्त होते हैं। तो आपका POCO इकाई फ्रेमवर्क के गतिशील रूप से निर्मित उपवर्गों के लिए एक आधार प्रकार के रूप में कार्य कर रहा है। यही मेरा मतलब है "चारों ओर एक छद्म बनाएं"।

गतिशील रूप से बनाई गई उपवर्ग जो कि एंटिटी फ्रेमवर्क बनाता है, जब रनटाइम में एंटिटी फ्रेमवर्क का उपयोग करते समय स्पष्ट हो जाता है, न कि स्थिर कंपाउंड समय पर। और केवल तभी जब आप एंटिटी फ्रेमवर्क की आलसी लोडिंग या ट्रैकिंग विशेषताओं को सक्षम करते हैं। यदि आप आलसी लोडिंग या एंटिटी फ्रेमवर्क की ट्रैकिंग विशेषताओं को बदलने का उपयोग नहीं करते हैं (जो डिफ़ॉल्ट नहीं है) तो आपको अपने किसी भी नेविगेशन गुण को आभासी घोषित करने की आवश्यकता नहीं है। फिर आप स्वयं उन नेविगेशन गुणों को लोड करने के लिए जिम्मेदार हैं, या तो एंटिटी फ्रेमवर्क का उपयोग "उत्सुक लोडिंग" के रूप में किया जाता है, या कई डेटाबेस प्रश्नों में संबंधित प्रकारों को मैन्युअल रूप से प्राप्त करने के लिए। आप हालांकि कई स्थितियों में अपने नेविगेशन गुणों के लिए आलसी लोडिंग और परिवर्तन ट्रैकिंग सुविधाओं का उपयोग कर सकते हैं।

यदि आप एक स्वसंपूर्ण वर्ग और चिह्न गुणों को आभासी के रूप में बनाने के लिए थे, और बस अपने स्वयं के अनुप्रयोग में उन वर्गों के उदाहरणों का निर्माण और उपयोग करें, जो पूरी तरह से इकाई ढांचे के दायरे से बाहर हैं, तो आपके आभासी गुण आपको उन पर कुछ भी हासिल नहीं करेंगे। खुद।

यह बताने के लिए संपादित करें कि गुणों को आभासी के रूप में क्यों चिह्नित किया जाएगा

गुण जैसे:

 public ICollection<RSVP> RSVPs { get; set; }

क्षेत्र नहीं हैं और ऐसा नहीं सोचा जाना चाहिए। इन्हें गेटर्स एंड सेटर कहा जाता है और संकलन के समय, इन्हें तरीकों में बदल दिया जाता है।

//Internally the code looks more like this:
public ICollection<RSVP> get_RSVPs()
{
    return _RSVPs;
}

public void set_RSVPs(RSVP value)
{
    _RSVPs = value;
}

private RSVP _RSVPs;

यही कारण है कि वे इकाई ढांचे में उपयोग के लिए आभासी के रूप में चिह्नित हैं, यह आंतरिक रूप से निर्मित कक्षाओं को आंतरिक रूप से उत्पन्न getऔर setकार्यों को ओवरराइड करने की अनुमति देता है । यदि आपका नेविगेशन प्रॉपर्टी गेट्टर / सेटर आपके एंटिटी फ्रेमवर्क के उपयोग में आपके लिए काम कर रहे हैं, तो उन्हें केवल गुणों, पुनर्मूल्यांकन में संशोधित करने का प्रयास करें, और देखें कि क्या एंटिटी फ्रेमवर्क अभी भी ठीक से काम करने में सक्षम है:

 public virtual ICollection<RSVP> RSVPs;

2
'क्रिएट अ प्रॉक्सी' के बारे में आपका क्या मतलब है? वास्तव में यहाँ क्या चल रहा है?
गैरी जोन्स

2
हाय गैरी, मैंने अपने उत्तर को स्पष्ट करने के लिए "मैं एक प्रॉक्सी बनाएं" से स्पष्ट किया। उम्मीद है कि इससे थोड़ी मदद मिलेगीं।
शान प्लौर्ड

2
"गुण ... गुण नहीं हैं" कहना काफी अशुभ है। सभी संपत्तियों को गेट्टर और / या सेटर विधियों के रूप में लागू किया जाता है, इसलिए यह कहने का कोई मतलब नहीं है कि "यह संपत्ति वास्तव में एक गेट्टर और सेटर विधि है जो संपत्ति नहीं है"।
बेन वोइगट

1
आपकी प्रतिक्रिया के लिए धन्यवाद बेन, मुझे स्पष्ट करना चाहिए कि "गुण फ़ील्ड नहीं हैं"। यदि आपके पास कोई अन्य प्रतिक्रिया या प्रश्न हैं तो मुझे बताएं।
शान प्लॉर्ड

मैंने शब्दों को बदल दिया और "गुण गुण नहीं हैं" को बेहतर तरीके से समझाने में मदद करने के लिए एक और कोड उदाहरण जोड़ा, कृपया यदि आप इसे नहीं चाहते हैं तो वापस रोल करें।
स्कॉट चैंबरलेन

75

virtualसी # में कीवर्ड सक्षम बनाता है एक विधि या संपत्ति बच्चे वर्गों द्वारा ओवरराइड करने के लिए। अधिक जानकारी के लिए कृपया 'वर्चुअल' कीवर्ड पर MSDN प्रलेखन देखें

अद्यतन: यह वर्तमान में पूछे गए प्रश्न का उत्तर नहीं देता है, लेकिन मैं इसे मूल , गैर-वर्णनात्मक प्रश्न के लिए एक सरल उत्तर की तलाश में किसी के लिए भी छोड़ दूँगा ।


23
@ यह सही नहीं है क्योंकि जो "सही" समझा जाता है वह केवल प्रश्न शीर्षक पर निर्भर नहीं करता है। मैं ज्यादातर लोगों की कल्पना करता हूं, खुद को और ओपी को शामिल किया गया है, पहले virtualएंटिटी फ्रेमवर्क के माध्यम से संपत्तियों के साथ सौदा करें - यहां तक ​​कि ओपी के शीर्षक में भी यह स्पष्ट नहीं है। स्वीकृत उत्तर इसलिए है क्योंकि यह चीजों के एंटिटी फ्रेमवर्क पक्ष को छूता है, और virtualउस संदर्भ में गुणों का उपयोग कैसे / क्यों किया जाता है।
डॉन चीडल

22

मैं ओपी हताशा को समझता हूं, वर्चुअल का यह उपयोग टेम्पर्ड एब्स्ट्रैक्शन के लिए नहीं है जो कि डिफेक्टो वर्चुअल मॉडिफायर के लिए प्रभावी है।

यदि कोई अभी भी इससे जूझ रहा है, तो मैं अपना दृष्टिकोण प्रस्तुत करूंगा, क्योंकि मैं समाधानों को सरल रखने की कोशिश करता हूं और शब्दजाल को न्यूनतम:

एक साधारण टुकड़े में एंटिटी फ्रेमवर्क आलसी लोडिंग का उपयोग करता है, जो कि भविष्य के निष्पादन के लिए किसी चीज को प्रस्तुत करने के बराबर है। यह 'वर्चुअल' संशोधक में फिट बैठता है, लेकिन इसमें और भी बहुत कुछ है।

एंटिटी फ्रेमवर्क में, वर्चुअल नेविगेशन प्रॉपर्टी का उपयोग करने से आप इसे SQL में एक अशक्त विदेशी कुंजी के बराबर बता सकते हैं। क्वेरी करते समय आप हर कुंजी तालिका में उत्सुकता से शामिल होने के लिए नहीं हैं, लेकिन जब आपको जानकारी की आवश्यकता होती है - तो यह मांग-संचालित हो जाता है।

मैंने भी अशक्त का उल्लेख किया क्योंकि कई नेविगेशन गुण पहले से प्रासंगिक नहीं हैं। यानी एक ग्राहक / आदेश परिदृश्य में, आपको उस समय तक इंतजार करने की आवश्यकता नहीं है जब तक कि ग्राहक बनाने के लिए एक आदेश संसाधित नहीं किया जाता है। आप कर सकते हैं, लेकिन यदि आपके पास इसे प्राप्त करने के लिए एक बहु-चरण प्रक्रिया थी, तो आपको ग्राहक डेटा को बाद में पूरा करने या भविष्य के आदेशों पर तैनाती के लिए जारी रखने की आवश्यकता हो सकती है । यदि सभी नौसेना संपत्तियों को लागू किया गया था, तो आपको प्रत्येक विदेशी कुंजी और रिलेशनल फ़ील्ड को सहेजना होगा। यह वास्तव में डेटा को स्मृति में वापस सेट करता है, जो दृढ़ता की भूमिका को पराजित करता है।

जब तक यह वास्तविक समय में वास्तविक निष्पादन में गूढ़ लग सकता है, मैंने पाया है कि उपयोग करने के लिए अंगूठे का सबसे अच्छा नियम होगा: यदि आप डेटा आउटपुट कर रहे हैं (एक दृश्य मॉडल या सीरियल मॉडल में पढ़ना) और संदर्भ से पहले मूल्यों की आवश्यकता है, नहीं आभासी का उपयोग करें; यदि आपका दायरा डेटा एकत्र कर रहा है जो अपूर्ण हो सकता है या खोज के लिए प्रत्येक खोज पैरामीटर को पूरा करने की आवश्यकता नहीं है, तो कोड को संदर्भ का अच्छा उपयोग करना होगा, अशक्त मूल्य गुणों का उपयोग करने के समान है? लंबा?। इसके अलावा, अपने व्यापार तर्क को अपने डेटा संग्रह से अलग करना जब तक कि इसे इंजेक्ट करने की आवश्यकता न हो, किसी वस्तु को त्वरित करने और इसे शून्य पर शुरू करने के समान कई प्रदर्शन लाभ हैं। एंटिटी फ्रेमवर्क बहुत अधिक प्रतिबिंब और गतिकी का उपयोग करता है, जो प्रदर्शन को नीचा दिखा सकता है, और एक लचीला मॉडल की आवश्यकता है जो मांग को माप सकता है प्रदर्शन के प्रबंधन के लिए महत्वपूर्ण है।

मेरे लिए, कि हमेशा अतिभारित टेक शब्दजाल जैसे कि परदे के पीछे, प्रतिनिधियों, हैंडलर और इस तरह के उपयोग से अधिक समझ में आता है। एक बार जब आप अपने तीसरे या चौथे प्रोग्रामिंग लैंग को मारते हैं, तो यह इनसे खिलवाड़ कर सकता है।


14

आभासी होने के लिए एक मॉडल में नेविगेशनल गुणों को परिभाषित करना काफी आम है। जब नेविगेशन प्रॉपर्टी को वर्चुअल के रूप में परिभाषित किया जाता है, तो यह निश्चित एंटिटी फ्रेमवर्क कार्यक्षमता का लाभ उठा सकता है। सबसे आम एक आलसी लोडिंग है।

आलसी लोडिंग कई ओआरएम की एक अच्छी विशेषता है क्योंकि यह आपको एक मॉडल से संबंधित डेटा को गतिशील रूप से एक्सेस करने की अनुमति देता है। यह अनावश्यक रूप से संबंधित डेटा को तब तक प्राप्त नहीं करेगा जब तक कि यह वास्तव में एक्सेस नहीं हो जाता है, इस प्रकार डेटाबेस से डेटा की अप-फ्रंट क्वेरी को कम कर देता है।

"ASP.NET MVC 5 से बूटस्ट्रैप और नॉकआउट। जेएस"


3

ईएफ के संदर्भ में, एक संपत्ति को आभासी के रूप में चिह्नित करना ईएफ को लोड करने के लिए आलसी लोडिंग का उपयोग करने की अनुमति देता है। काम करने के लिए आलसी लोडिंग के लिए ईएफ को एक प्रॉक्सी ऑब्जेक्ट बनाना पड़ता है जो आपके वर्चुअल गुणों को एक कार्यान्वयन के साथ ओवरराइड करता है जो संदर्भित इकाई को पहली बार एक्सेस करने पर लोड करता है। यदि आप संपत्ति को आभासी के रूप में चिह्नित नहीं करते हैं तो आलसी लोडिंग इसके साथ काम नहीं करेगी।


0

वर्चुअल कीवर्ड का उपयोग किसी विधि, गुण, अनुक्रमणिका या ईवेंट घोषणा को संशोधित करने और एक व्युत्पन्न वर्ग में इसे ओवरराइड करने की अनुमति देने के लिए किया जाता है। उदाहरण के लिए, इस पद्धति को किसी भी वर्ग द्वारा ओवरराइड किया जा सकता है जो इसे विरासत में देता है:

public virtual double Area() 
{
    return x * y;
}

आप स्थिर, सार, निजी या ओवरराइड संशोधक के साथ आभासी संशोधक का उपयोग नहीं कर सकते। निम्न उदाहरण एक आभासी संपत्ति दिखाता है:

class MyBaseClass
{
    // virtual auto-implemented property. Overrides can only
    // provide specialized behavior if they implement get and set accessors.
    public virtual string Name { get; set; }

    // ordinary virtual property with backing field
    private int num;
    public virtual int Number
    {
        get { return num; }
        set { num = value; }
    }
}


class MyDerivedClass : MyBaseClass
{
    private string name;

    // Override auto-implemented property with ordinary property
    // to provide specialized accessor behavior.
    public override string Name
    {
        get
        {
            return name;
        }
        set
        {
            if (value != String.Empty)
            {
                name = value;
            }
            else
            {
                name = "Unknown";
            }
        }
    }
}

यह पूरी तरह से विषय भाई से बाहर है।
इरु

0

हम बहुरूपता का जिक्र किए बिना आभासी सदस्यों के बारे में बात नहीं कर सकते । वास्तव में, वर्चुअल के रूप में चिह्नित बेस क्लास में एक फ़ंक्शन, प्रॉपर्टी, इंडेक्सर या ईवेंट एक व्युत्पन्न वर्ग से ओवरराइड करने की अनुमति देगा।

डिफ़ॉल्ट रूप से, एक वर्ग के सदस्य गैर-आभासी होते हैं और उन्हें चिह्नित नहीं किया जा सकता है, यदि स्थिर, सार, निजी या ओवरराइड संशोधक।

उदाहरण आइए System.Object में ToString () विधि पर विचार करें । क्योंकि यह विधि System.Object का सदस्य है, जो इसे सभी वर्गों में विरासत में मिला है और इन सभी को ToString () तरीके प्रदान करेगा।

namespace VirtualMembersArticle
{
    public class Company
    {
        public string Name { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Company company = new Company() { Name = "Microsoft" };
            Console.WriteLine($"{company.ToString()}");
            Console.ReadLine();
        }   
    }
}

पिछले कोड का आउटपुट है:

VirtualMembersArticle.Company

आइए विचार करें कि हम ToString के मानक व्यवहार को बदलना चाहते हैं () हमारे Company वर्ग में System.Object से विरासत में मिली विधियों। इस लक्ष्य को प्राप्त करने के लिए उस पद्धति का एक और कार्यान्वयन घोषित करने के लिए ओवरराइड कीवर्ड का उपयोग करना पर्याप्त है।

public class Company
{
    ...
    public override string ToString()
    {
        return $"Name: {this.Name}";
    }         
}

अब, जब कोई वर्चुअल विधि लागू की जाती है, तो रन-टाइम अपने व्युत्पन्न वर्ग में एक ओवरराइडिंग सदस्य के लिए जाँच करेगा और यदि मौजूद है तो उसे कॉल करेगा। हमारे आवेदन का उत्पादन तब होगा:

Name: Microsoft

वास्तव में, यदि आप System.Object क्लास की जांच करते हैं, तो आप पाएंगे कि विधि आभासी के रूप में चिह्नित है।

namespace System
{
    [NullableContextAttribute(2)]
    public class Object
    {
        ....
        public virtual string? ToString();
        ....
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.