2010-01-23 1 views
5

Je commence à passer à memcached et je suis en train de tester avec memcached.Y at-il de toute façon pour sériliser l'objet linq pour Memcached?

Je vais avoir 2 objet, je créé un objet et mis [Serializable] sur elle (par exemple, laisser appeler ce Object1), l'autre objet est créé en utilisant Linq DBML (Object2) ..

I essayé de memcached List<Object1>, cela fonctionne très bien, comme le charme, tout ici est le cache et chargé correctement.

Mais ensuite, je passe à l'objet Linq, maintenant j'essaie d'ajouter à memcached List<Object2> cela ne fonctionne pas, il n'a pas ajouté à memcached du tout. aucune clé n'a été ajoutée

Je passe à autre chose et change le mode de sérialisation en unidirectionnel, refait l'ajout, toujours pas d'espoir.

Y a-t-il un moyen de le faire fonctionner?

Voici le test simple que je viens d'écrire, en utilisant MemcachedProvider de CodePlex pour démontrer:

public ActionResult Test() 
{ 
    var returnObj = DistCache.Get<List<Post>>("testKey"); 
    if (returnObj == null) 
    { 
     DataContext _db = new DataContext(); 
     returnObj = _db.Posts.ToList(); 
     DistCache.Add("testKey", returnObj, new TimeSpan(29, 0, 0, 0)); 
     _db.Dispose(); 
    } 

    return Content(returnObj.First().TITLE); 
} 

c'est de Memcached, aucun magasin a été appelé:

> NOT FOUND _x_testKey 
>532 END 
<528 get _x_testKey 
> NOT FOUND _x_testKey 
>528 END 
<516 get _x_testKey 
> NOT FOUND _x_testKey 
>516 END 

Et dans mon profileur SQL, il a appelé 3 requête pour 3 temps de test => prouvé que l'objet rappelé de Memcached est nul, alors il requête.

+0

Cette question pourrait bénéficier de (1) Quelques exemples de code (2) explication plus claire de ce qui se passe mal exactement et (3) Comment exactement vous utilisez memcached de .NET. Il existe plusieurs wrappers .NET et ils peuvent ne pas tous se comporter de la même manière à cet égard. –

+0

J'ai ajouté tout ce dont vous avez besoin. Le wrapper im using est MemcachedProvider de codeplex. L'objet1 a été ajouté avec succès, mais l'objet linq ne l'a pas fait. – DucDigital

+0

L'info supplémentaire aide, mais je ne vois pas de problème. Avez-vous débogué l'appel Add()? Qu'en est-il de l'utilisation d'un proxy TCP ou Wireshark pour voir si MemcachedProvider envoie même quelque chose à memcached pour cette requête? –

Répondre

2

Il semble que l'implémentation par défaut (DefaultTranscoder) utilise BinaryFormatter; le truc "unidirectionnel" est une instruction à un sérialiseur différent (DataContractSerializer), et ne ajoute [Serializable].

(Note: J'ai ajouté un memo to myself pour essayer d'écrire un transcodeur protobuf-net memcached, ce serait frais et fixerait plus cela gratuitement)

Je ne l'ai pas testé, mais quelques options se présentent:

  1. écrire une autre implémentation transcodeur qui détecte [DataContract] et utilise DataContractSerializer, et le crochet ce transcodeur
  2. ajouter [Serializable] à vos types via une classe partielle (Je ne suis pas convaincu que cela fonctionnera en raison des types de champs LINQ ne pas être sérialisables)
  3. ajouter une implémentation ISerializable dans une classe partielle qui utilise DataContractSerializer
  4. comme 3, mais en utilisant protobuf-net, qui a: travaille avec « unidirectionnel », et b: est plus rapide et plus petit que DataContractSerializer
  5. écrire un DTO sérialisable et mapper vos types de que

Le dernier est simple mais peut ajouter plus de travail.

Je serais tenté de regarder d'abord la 3ème option, car la première implique la reconstruction du fournisseur; la 4ème option serait également certainement être sur ma liste de choses à tester.


I lutté avec 3, en raison de la DCS renvoyant un objet différent pendant la désérialisation; Je suis passé à protobuf-net à la place, donc voici une version qui montre l'ajout d'un partial class à votre type existant [DataContract] qui le fait fonctionner avec BinaryFormatter. En fait, je soupçonne (avec preuve) cela également beaucoup plus efficace (que [Serializable] brut) aussi:

using System; 
using System.IO; 
using System.Runtime.Serialization; 
using System.Runtime.Serialization.Formatters.Binary; 
using ProtoBuf; 

/* DBML generated */ 
namespace My.Object.Model 
{ 
    [DataContract] 
    public partial class MyType 
    { 
     [DataMember(Order = 1)] 
     public int Id { get; set; } 

     [DataMember(Order = 2)] 
     public string Name { get; set; } 
    } 
} 
/* Your extra class file */ 
namespace My.Object.Model 
{ 
    // this adds **extra** code into the existing MyType 
    [Serializable] 
    public partial class MyType : ISerializable { 
     public MyType() {} 
     void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { 
      Serializer.Serialize(info, this); 
     } 
     protected MyType(SerializationInfo info, StreamingContext context) { 
      Serializer.Merge(info, this); 
     } 
    } 
} 
/* quick test via BinaryFormatter */ 
namespace My.App 
{ 
    using My.Object.Model; 
    static class Program 
    { 
     static void Main() 
     { 
      BinaryFormatter bf = new BinaryFormatter(); 
      MyType obj = new MyType { Id = 123, Name = "abc" }, clone; 
      using (MemoryStream ms = new MemoryStream()) 
      { 
       bf.Serialize(ms, obj); 
       ms.Position = 0; 
       clone = (MyType)bf.Deserialize(ms); 
      } 
      Console.WriteLine(clone.Id); 
      Console.WriteLine(clone.Name); 
     } 
    } 
} 
+0

J'ai ajouté un commentaire sur votre problème, pouvez-vous vérifier? – DucDigital

Questions connexes