Récupération de XML à partir d'une base de données avec Dapper

dapper

Question

J'utilise Dapper pour interroger une table qui inclut un champ XML:

CREATE TABLE Workflow
(
    Guid uniqueidentifier not null,
    State xml not null
)

qui est ensuite mappé sur une propriété de type XDocument:

public class Workflow
{
    public Guid InstanceId { get;set; }
    public XDocument State { get;set; }
}

mais quand j'essaie d'interroger la table, j'obtiens l'erreur suivante:

Error parsing column 1 (State= - String)
   at Dapper.SqlMapper.ThrowDataException(Exception ex, Int32 index, IDataReader reader, Object value) in d:\\Dev\\dapper-dot-net\\Dapper NET40\\SqlMapper.cs:line 4045
   at Deserialize038b29f4-d97d-4b62-b45b-786bd7d50e7a(IDataReader )
   at Dapper.SqlMapper.<QueryImpl>d__11`1.MoveNext() in d:\\Dev\\dapper-dot-net\\Dapper NET40\\SqlMapper.cs:line 1572
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in d:\\Dev\\dapper-dot-net\\Dapper NET40\\SqlMapper.cs:line 1443
   at MyProject.DapperBase.Query[TResult](String command, DynamicParameters parameters, IDbTransaction transaction, Boolean buffered, Int32 commandTimeout) in d:\\MyProject\\DapperBase.cs:line 122
   at MyProject.WorkflowData.Get(Guid identifier) in d:\\MyProject\\WorkflowData.cs:line 41
   at MyProject.WorkflowLogic.Save(Workflow workflow) in d:\\MyProject\\WorkflowLogic.cs:line 34
   at MyProject.WorkflowsController.Save(Guid id, WorkflowRequest request) in d:\\MyProject\\WorkflowsController.cs:line 97

InnerException: Invalid cast from 'System.String' to 'System.Xml.Linq.XDocument'.
    at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
    at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
    at System.Convert.ChangeType(Object value, Type conversionType)
    at Deserialize038b29f4-d97d-4b62-b45b-786bd7d50e7a(IDataReader )

En dehors de la modification de mon POCO pour utiliser un type de données de chaîne puis convertir la chaîne ailleurs dans un XDocument, existe-t-il un moyen d’obtenir que Dapper désérialise correctement le XML à partir de la base de données?

Réponse acceptée

En fin de compte, je viens de le forcer brutalement:

public class Workflow
{
    public Guid InstanceId { get;set; }
    public XDocument StateIn { set { State = value.ToString(); } }
    public string State { get;set; }
    public XDocument StateOut { get { return XDocument.Parse(State); } }
}

Dapper joue avec la valeur State et je ne fais que définir la valeur sur StateIn et la lire dans StateOut. Je me sens un peu sale en proposant une solution comme celle-ci, mais bon, ça marche.


Réponse populaire

Peut-être que la création d'un gestionnaire de type personnalisé peut aider? Quelque chose comme:

public class XDocumentTypeHandler : SqlMapper.TypeHandler<XDocument>
{
    public override void SetValue(IDbDataParameter parameter, XDocument value)
    {
       // set value in db parameter.
    }

    public XDocument Parse(object value)
    {
       // parse value from db to an XDocument.
    }
}

Vous devez ajouter le gestionnaire de type avec SqlMapper.AddTypeHandler() .

Voir le blogpost introduisant le blogpost et un exemple de mise en œuvre .



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi