2011-11-25 9 views
6

हम डेटा एक्सेस के लिए एनएच का उपयोग कर एएसपी.नेट एमवीसी अनुप्रयोग बना रहे हैं। एनएच प्रोफाइलर का उपयोग करके मुझे कई चेतावनियां दिखाई देती हैं जैसे "चेतावनी: डोमेन पर प्रॉक्सी को संक्षिप्त करना। केस टास्क - यह ऑपरेशन ब्रेक =="। मैं इन मिल बहुत बार जब जो उपवर्ग प्रति किसी तालिका में मैप किया जाता है, उदाहरण के लिए कक्षाओं के लिए प्रश्नों को क्रियान्वित करने, राष्ट्रीय राजमार्ग LINQ प्रदाता का उपयोग कर:NHibernate संकीर्ण प्रॉक्सी चेतावनी

Query<ICaseTask>().Where(c => c.Assignee == Of || c.Operator == Of) 

जहां वर्ग CaseTask टास्क से विरासत, चेतावनी से चलाता है।

इंटरनेट में चेतावनी के बारे में जानकारी दुर्लभ है और ज्यादातर संकेत देती है कि यह अनदेखा करने के लिए कुछ है ... यह चेतावनी वास्तव में क्या चेतावनी देती है? क्या यह कुछ ऐसा होना चाहिए जो मुझे सही करना चाहिए?

उत्तर

2

यह चेतावनी उन वर्गों या फ़ील्ड वाले वर्गों के बारे में है जो उप-वर्ग हैं। आईई:

public class Animal 
{ 
    public int Id {get;set;} 
} 

public class Cat : Animal 
{ 
    public int Weight {get;set;} 
} 

public class Person 
{ 
    public Cat Pet {get;set;} 
} 

NHibernate परेशान हो जाता है जब यह व्यक्ति इकाई, क्योंकि यह आप के लिए कास्ट करने के लिए नहीं चाहता है क्योंकि व्यवहार अप्रत्याशित हो जाता है लोड करता है। जब तक आप एनएचबीर्नेट को बराबर (अन्य तर्क के साथ) से निपटने के बारे में बताते हैं, तो यह नहीं पता होगा कि तुलनात्मक रूप से इसकी तुलना कैसे करें।

एनएचबर्ननेट को बेस क्लास ऑब्जेक्ट को ग्राफ़ में डालने देना मूलभूत विचार है और फिर आप कास्टिंग से निपटते हैं (ध्यान दें कि यह सेटअप कुछ अलग मैपिंग का उपयोग करेगा - यह कोड को सरल बनाने के लिए किया गया है लेकिन यह गुणों को पूर्ण गेटर्स/सेटर्स के रूप में रखकर किया जा सकता है):

public class Animal 
    { 
     public int Id {get;set;} 
    } 

public class Cat : Animal 
{ 
    public int Weight {get;set;} 
} 

public class Person 
{ 
    private Animal _pet; 
    public Cat Pet { 
     get{return _pet as Cat;} 
    } 
} 
+0

क्या यह एक बड़ा सौदा है? अगर हम इस चेतावनी को अनदेखा करते हैं तो क्या होता है? – Beatles1692

+1

यह एक बड़ा सौदा है या नहीं, उस जोखिम के स्तर पर निर्भर करता है जिसे आप स्वीकार करना चाहते हैं। चूंकि आपके कोड और आपके डेटाबेस के बीच हमेशा डिस्कनेक्ट होने जा रहा है, इसलिए आप हमेशा यह सुनिश्चित नहीं कर सकते कि कास्टिंग काम करेगा। यह उन बगों का कारण बन जाएगा जो निदान करना मुश्किल हो सकता है और डेटाबेस या कोड में बदलाव किए बिना हल नहीं किया जा सकता है। – Fourth

2

वास्तविकता अधिक जटिल है। जब आप session.Load का उपयोग करके इकाई लोड करते हैं या आप ऐसी संपत्ति तक पहुंचते हैं जो आलसी लोडेड NHibernate प्रॉक्सी ऑब्जेक्ट देता है। उस प्रॉक्सी ऑब्जेक्ट हाइड्रेटेड द्वारा किया जाएगा (डेटा डीबी से लोड किया जाएगा) जब आप पहली बार अपनी किसी भी संपत्ति का उपयोग करते हैं। यह एनएचबीर्नेट प्राप्त करने के लिए प्रॉक्सी क्लास उत्पन्न करता है जो इकाई वर्ग बढ़ाता है और सभी संपत्ति गेटर्स और सेटर्स को ओवरराइड करता है। यह पूरी तरह से काम करता है जब विरासत का उपयोग नहीं किया जाता है क्योंकि आपके पास प्रॉक्सी और इकाई वर्ग (प्रॉक्सी बेस क्लास) के बीच अंतर करने का कोई तरीका नहीं होगा, उदा। सरल परीक्षण proxy is MyEntity हमेशा काम करेगा।

अब कल्पना है कि हम एक व्यक्ति इकाई है:

class Person { 
    // lazy-loaded 
    public Animal Pet { get; set; } 
} 

और हम भी Animal वर्ग पदानुक्रम है:,

public abstract class Animal { ... } 
public class Cat { ... } 
public class Dog { ... } 

अब मान लेते हैं कि Pet संपत्ति आलसी लोड होता है जब आप व्यक्ति के लिए NHibernate पूछना पालतू जानवर आपको प्रॉक्सी ऑब्जेक्ट मिलेगा:

var pet = somePerson.Pet; // pet will be a proxy 

लेकिन Pet आलसी लोड की गई संपत्ति है, एनएच यह नहीं जान पाएगा कि यह Cat या Dog का उदाहरण होगा, इसलिए यह सबसे अच्छा होगा और एक प्रॉक्सी बनाएगा जो Animal बढ़ाता है। प्रॉक्सी pet is Animal के लिए परीक्षण पास करेगी लेकिन pet is Cat या pet is Dog के लिए परीक्षण विफल हो जाएगी।

अब मान लें कि आप pet ऑब्जेक्ट की कुछ संपत्ति तक पहुंचेंगे, जिससे एनएच डीबी से डेटा लोड कर सके। अब एनएच को पता चलेगा कि आपके पालतू जानवर उदा। एक Cat लेकिन प्रॉक्सी पहले से ही जेनरेट की गई है और इसे बदला नहीं जा सकता है। यह एनएचबीर्नेट को चेतावनी जारी करने के लिए मजबूर करेगा कि pet के लिए मूल प्रॉक्सी Animal टाइप Cat टाइप करने के लिए संकुचित हो जाएगी। इसका मतलब है कि पर pet.Id के साथ जानवर के लिए प्रॉक्सी ऑब्जेक्ट से session.Load<Animal>(pet.Id) का उपयोग करके आप Cat का विस्तार करेंगे। इसका मतलब यह भी है कि Cat अब सत्र के एक हिस्से के रूप में संग्रहीत है, अगर हम पहले व्यक्ति के साथ बिल्ली साझा करने वाले दूसरे व्यक्ति को लोड करते हैं, तो एनएच आलसी लोड की गई संपत्ति को पॉप्युलेट करने के लिए पहले ही उपलब्ध Cat प्रॉक्सी उदाहरण का उपयोग करेगा।

परिणामों में से एक यह होगा कि pet पर ऑब्जेक्ट संदर्भ session.Load<Animal>(pet.Id) (object.ReferencesEqual समझ में) द्वारा प्राप्त संदर्भ अलग होगा।

अब

जब यह आपके लिए नुकसान का कारण हो सकता है:

  1. जब आप Set रों करने या अपने कोड में Dictionary एँ या में अपने संस्थाओं डाल आप किसी भी अन्य संरचना कि Equals/GetHashCode जोड़ी काम करने की आवश्यकता है का उपयोग करता है, तो । इसे कस्टम Equals/GetHashCode कार्यान्वयन प्रदान करके आसानी से तय किया जा सकता है (देखें: http://www.onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page=1)

  2. जब आप अपनी प्रॉक्सी ऑब्जेक्ट को लक्ष्य प्रकार पर डालने का प्रयास करते हैं उदा। (Cat)pet, लेकिन फिर वहाँ समाधान पता कर रहे हैं (जैसे Getting proxies of the correct type in NHibernate)

तो नैतिक आपके डोमेन मॉडल में संभव विरासत के रूप में के रूप में ज्यादा से बचना है।