2009-07-27 12 views
7

मेरे पास कुछ वेब विधियां हैं जो मेरी ऑब्जेक्ट को क्रमबद्ध XML के रूप में वापस लौटाती हैं। यह केवल वस्तु के NHibernate- मैप किए गए गुणों को क्रमबद्ध कर रहा है ... किसी के पास कुछ अंतर्दृष्टि है? ऐसा लगता है कि वेब विधियां वास्तव में मेरी कक्षाओं के बजाय एनएचबेर्नेट प्रॉक्सी को क्रमबद्ध कर रही हैं। मैंने [XMLInclude] और [XMLElement] का उपयोग करने का प्रयास किया है, लेकिन गुण अभी भी क्रमबद्ध नहीं हैं। मेरे पास इस के आसपास होने का एक बहुत ही भयानक हैकिश तरीका है, लेकिन मुझे आश्चर्य हुआ कि क्या कोई बेहतर तरीका था!मैं एनएचबीर्नेट-मैप किए गए ऑब्जेक्ट के सभी गुणों को क्रमबद्ध कैसे करूं?

कुछ इस तरह:

<?xml version="1.0" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="StoryManager" assembly="StoryManager"> 
    <class name="Graphic" table="graphics" lazy="false"> 
    <id name="Id" column="id" type="int" unsaved-value="0" > 
     <generator class="identity"/> 
    </id> 

    <property name="Assigned" /> 
    <property name="Due" /> 
    <property name="Completed" /> 
    <property name="UglyHack" insert="false" update="false" /> 


    <many-to-one name="Parent" class="Story" column="story_id"/> 

    </class> 
</hibernate-mapping> 

public class Graphic 
{ 
    private int m_id; 
    public virtual int Id 
    { 
     get { return m_id; } 
     set { m_id = value; } 
    } 

    private DateTime? m_assigned; 
    public virtual DateTime? Assigned 
    { 
     get { return m_assigned; } 
     set { m_assigned = value; } 
    } 

    private DateTime? m_due; 
    public virtual DateTime? Due 
    { 
     get { return m_due; } 
     set { m_due = value; } 
    } 

    private DateTime? m_completed; 
    public virtual DateTime? Completed 
    { 
     get { return m_completed; } 
     set { m_completed = value; } 
    } 

    public bool UglyHack 
    { 
     get { return m_due < m_completed; } // return something besides a real mapped variable 
     set {} // trick NHibernate into thinking it's doing something 
    } 
} 

यह स्पष्ट रूप से कोई रास्ता नहीं कोड लिखने के लिए है। अगर मेरे पास "नकली" मैपिंग नहीं है (UglyHack संपत्ति), तो उस संपत्ति को क्रमबद्ध नहीं किया जाएगा। अभी के लिए मैं (डेटा) ट्रांसफर ऑब्जेक्ट्स का उपयोग कर रहा हूं, और प्रतिबिंब का उपयोग कर कुछ पर हो सकता है ...

+0

एक छोटा सा उदाहरण पोस्ट करें। –

उत्तर

21

एनएच मैप किए गए ऑब्जेक्ट को क्रमबद्ध करने का सबसे अच्छा तरीका यह है कि इसे क्रमबद्ध नहीं किया जाए :)।

यदि आप इसे तार में भेज रहे हैं तो आपको इसके लिए एक डीटीओ बनाना चाहिए। यदि आप उस ऑब्जेक्ट को नहीं बनाना चाहते हैं तो आप उन गुणों पर [XmlIgnore] सेट कर सकते हैं जिन्हें आप क्रमबद्ध नहीं करना चाहते हैं।

यदि आप सभी गुण चाहते हैं, तो आपको उन्हें डेटाबेस से सभी लोड करना होगा - कुछ लोगों के लिए एक उत्सुक भार पर्याप्त होगा (जहां बहुत से लोग डेटा डुप्लिकेट करना शुरू कर देंगे) आपको उस संपत्ति को किसी भी में एक्सेस करना होगा जिस तरह से आप लोड ट्रिगर करना चाहते हैं।

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

और मैं एक और बात जोड़ना चाहते हैं - तार के साथ आपके डोमेन संस्थाओं भेजने हमेशा एक बुरा विचार है। मेरे मामले में मैंने इसे कठिन तरीके से सीखा - मैं एक वेब सेवा पर कुछ इकाइयों का पर्दाफाश करता हूं - और अब लगभग किसी भी बदलाव (एक संपत्ति का नाम बदलें, एक संपत्ति ..etc हटाएं) मेरे डोमेन में डब्ल्यूएस - प्लस का एक पूरा समूह का उपयोग करके ऐप को मारता है गुणों पर [XmlIgnore] है (परिपत्र निर्भरताओं के बारे में मत भूलना)।

हम जल्द ही एक पुनर्लेखन करेंगे - लेकिन बाकी आश्वस्त करें कि मैं कुछ नहीं हूं कभी फिर से करें। :)

संपादित 2

आप डीटीओ करने के लिए अपने इकाई से डेटा स्थानांतरित करने के लिए AutoMapper इस्तेमाल कर सकते हैं। उनके पास साइट पर कुछ उदाहरण हैं।

+0

टिप के लिए धन्यवाद! – wprl

+0

मैं तुम्हारा बिंदु देखता हूं :) अब मैं सिर्फ यह समझने की कोशिश कर रहा हूं कि प्रतिबिंब के माध्यम से उन्हें कैसे उत्पन्न किया जाए ... – wprl

+1

+1 उत्कृष्ट उत्तर! –

0

सिरोक्रो के साथ सहमत हैं, मेरे पास डब्ल्यूसीएफ के माध्यम से एनएचबीरनेट इकाइयों को क्रमबद्ध करने का प्रयास करने का सबसे भयानक समय है, और अंत में प्रतिबिंब के माध्यम से सामान्य रूप से किए गए डीटीओ समाधान के साथ चला गया।

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

[DataContract] 
public class DataTransferObject 
{ 
    private Dictionary<string, object> propertyValues = new Dictionary<string, object>(); 
    private Dictionary<string, object> fieldValues = new Dictionary<string, object>(); 
    private Dictionary<string, object> relatedEntitiesValues = new Dictionary<string, object>(); 
    private Dictionary<string, object> primaryKey = new Dictionary<string, object>(); 
    private Dictionary<string,List<DataTransferObject>> subEntities = new Dictionary<string, List<DataTransferObject>>(); 

... 

    public static DataTransferObject ConvertEntityToDTO(object entity,Type transferType) 
    { 
     DataTransferObject dto = new DataTransferObject(); 
     string[] typePieces = transferType.AssemblyQualifiedName.Split(','); 

     dto.AssemblyName = typePieces[1]; 
     dto.TransferType = typePieces[0]; 

     CollectPrimaryKeyOnDTO(dto, entity); 
     CollectPropertiesOnDTO(dto, entity); 
     CollectFieldsOnDTO(dto, entity); 
     CollectSubEntitiesOnDTO(dto, entity); 
     CollectRelatedEntitiesOnDTO(dto, entity); 

     return dto; 
    } 
.... 

    private static void CollectPropertiesOnDTO(DataTransferObject dto, object entity) 
    { 
     List<PropertyInfo> transferProperties = ReflectionHelper.GetProperties(entity,typeof(PropertyAttribute)); 

     CollectPropertiesBasedOnFields(entity, transferProperties); 

     foreach (PropertyInfo property in transferProperties) 
     { 
      object propertyValue = ReflectionHelper.GetPropertyValue(entity, property.Name); 

      dto.PropertyValues.Add(property.Name, propertyValue); 
     } 
    } 

, :

private static DTOConversionResults ConvertDTOToEntity(DataTransferObject transferObject,object parent) 
    { 
     DTOConversionResults conversionResults = new DTOConversionResults(); 

     object baseEntity = null; 
     ObjectHandle entity = Activator.CreateInstance(transferObject.AssemblyName, 
                 transferObject.TransferType); 

     if (entity != null) 
     { 
      baseEntity = entity.Unwrap(); 

      conversionResults.Add(UpdatePrimaryKeyValue(transferObject, baseEntity)); 
      conversionResults.Add(UpdateFieldValues(transferObject, baseEntity)); 
      conversionResults.Add(UpdatePropertyValues(transferObject, baseEntity)); 
      conversionResults.Add(UpdateSubEntitiesValues(transferObject, baseEntity)); 
      conversionResults.Add(UpdateRelatedEntitiesValues(transferObject, baseEntity,parent)); 
.... 

    private static DTOConversionResult UpdatePropertyValues(DataTransferObject transferObject, object entity) 
    {    
     DTOConversionResult conversionResult = new DTOConversionResult(); 

     foreach (KeyValuePair<string, object> values in transferObject.PropertyValues) 
     { 
      try 
      { 
       ReflectionHelper.SetPropertyValue(entity, values.Key, values.Value); 
      } 
      catch (Exception ex) 
      { 
       string failureReason = "Failed to set property " + values.Key + " value " + values.Value; 

       conversionResult.Failed = true; 
       conversionResult.FailureReason = failureReason; 

       Logger.LogError(failureReason); 
       Logger.LogError(ExceptionLogger.BuildExceptionLog(ex)); 
      } 
     } 

     return conversionResult; 
    } 
+0

एक उदाहरण पोस्ट करने की देखभाल? – wprl

+0

बहुत रोचक – wprl

+1

ऑटोमैपर इस कार्य को नहीं करेगा? – Lijo

4

अगर इसकी एक WCF सेवा, आप एक IDataContractSurrogate

public class HibernateDataContractSurrogate : IDataContractSurrogate 
{ 
    public HibernateDataContractSurrogate() 
    { 
    } 

    public Type GetDataContractType(Type type) 
    { 
     // Serialize proxies as the base type 
     if (typeof(INHibernateProxy).IsAssignableFrom(type)) 
     { 
      type = type.GetType().BaseType; 
     } 

     // Serialize persistent collections as the collection interface type 
     if (typeof(IPersistentCollection).IsAssignableFrom(type)) 
     { 
      foreach (Type collInterface in type.GetInterfaces()) 
      { 
       if (collInterface.IsGenericType) 
       { 
        type = collInterface; 
        break; 
       } 
       else if (!collInterface.Equals(typeof(IPersistentCollection))) 
       { 
        type = collInterface; 
       } 
      } 
     } 

     return type; 
    } 

    public object GetObjectToSerialize(object obj, Type targetType) 
    { 
     // Serialize proxies as the base type 
     if (obj is INHibernateProxy) 
     { 
      // Getting the implementation of the proxy forces an initialization of the proxied object (if not yet initialized) 
      try 
      { 
       var newobject = ((INHibernateProxy)obj).HibernateLazyInitializer.GetImplementation(); 
       obj = newobject; 
      } 
      catch (Exception) 
      { 
       // Type test = NHibernateProxyHelper.GetClassWithoutInitializingProxy(obj); 
       obj = null; 
      } 
     } 

     // Serialize persistent collections as the collection interface type 
     if (obj is IPersistentCollection) 
     { 
      IPersistentCollection persistentCollection = (IPersistentCollection)obj; 
      persistentCollection.ForceInitialization(); 
      //obj = persistentCollection.Entries(); // This returns the "wrapped" collection 
      obj = persistentCollection.Entries(null); // This returns the "wrapped" collection 
     } 

     return obj; 
    } 



    public object GetDeserializedObject(object obj, Type targetType) 
    { 
     return obj; 
    } 

    public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType) 
    { 
     return null; 
    } 

    public object GetCustomDataToExport(Type clrType, Type dataContractType) 
    { 
     return null; 
    } 

    public void GetKnownCustomDataTypes(Collection<Type> customDataTypes) 
    { 
    } 

    public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData) 
    { 
     return null; 
    } 

    public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit) 
    { 
     return typeDeclaration; 
    } 
} 

implemen इस्तेमाल कर सकते हैं मेजबान में Taion:

foreach (ServiceEndpoint ep in host.Description.Endpoints) 
     { 
      foreach (OperationDescription op in ep.Contract.Operations) 
      { 
       var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>(); 
       if (dataContractBehavior != null) 
       { 
        dataContractBehavior.DataContractSurrogate = new HibernateDataContractSurrogate(); 
       } 
       else 
       { 
        dataContractBehavior = new DataContractSerializerOperationBehavior(op); 
        dataContractBehavior.DataContractSurrogate = new HibernateDataContractSurrogate(); 
        op.Behaviors.Add(dataContractBehavior); 
       } 
      } 
     } 
संबंधित मुद्दे

 संबंधित मुद्दे