J'ai des méthodes Web qui renvoient mes objets en tant que XML sérialisé. Serialiser uniquement les propriétés cartographiées de NHibernate de l'objet ... Tout le monde a une idée? Il semble que les méthodes Web soient en train de sérialiser les proxies NHibernate au lieu de mes classes. J'ai essayé d'utiliser [xmlinclude] et [xmlelement], mais les propriétés ne sont toujours pas sérialisées. J'ai une façon vraiment horrible de me déplacer, mais je me demandais s'il y avait une meilleure façon!
Quelque chose comme ceci: p>
<?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 } }
3 Réponses :
Le meilleur moyen de sérialiser l'objet mappé NH est de ne pas le sérialiser :). p>
Si vous l'envoyez sur le fil, vous devez vraiment créer un DTO pour cela. Si vous ne voulez pas créer cet objet, vous pouvez définir [xmlignore] sur les propriétés que vous ne voulez pas sérialiser. p>
Si vous voulez toutes les propriétés, vous devez les charger tous de la base de données - car une charge désireuse suffira à d'autres (où trop de jointures commenceront à dupliquer les données), vous devrez accéder à cette propriété de quelque manière que ce soit. Vous voulez déclencher la charge. P>
Et j'aimerais ajouter une autre chose - envoyer vos entités de domaine sur le fil est Nous ferons une réécriture suffisamment de temps - mais vous assure que ce n'est pas quelque chose que je vais Vous pouvez utiliser Automapper pour transférer les données de votre entité vers le DTO. Ils ont quelques exemples sur le site. P>
Je vois ton point :) Maintenant, j'essaie juste de comprendre comment les générer à réflexion ...
D'accord avec Sirrocco, j'ai eu le temps le plus affreux qui tente de sérialiser les entités de NHibernate à travers la WCF et devenue éventuellement une solution DTO effectuée de manière générique par réflexion.
Edit: Toute la solution est trop grande pour poster ici, et est personnalisé pour mes besoins de succès, donc je posterai quelques sections pertinentes: p> puis, lorsque vous souhaitez ressusciter le DTO: P> 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;
}
Ne sera-t-il pas automappé cette tâche?
Si son service WCF, vous pouvez utiliser une implémentation IDataContractSurrogate dans l'hôte: p>