Есть ли способ сериализовать объект linq для Memcached? - PullRequest
5 голосов
/ 23 января 2010

Я только начинаю переключаться на memcached и в настоящее время на тестировании с memcached.

У меня есть 2 объекта, я создал объект и поместил на него [Serializable] (например, позвольте вызвать это Object1), другой объект создан с использованием Linq DBML (Object2) ..

Я попытался memcached List<Object1>, он работает просто отлично, как шарм, все здесь кеш и загружен правильно.

Но затем я перехожу к объекту Linq, теперь я пытаюсь добавить в memcached List<Object2> это не работает, оно вообще не добавляется в memcached. ключ не был добавлен

Я перехожу и изменяю режим сериализации на Однонаправленный, делаю добавление снова, все еще без надежды.

Есть ли способ заставить это работать?

Вот простой тест, который я только что написал, используя MemcachedProvider из codeplex для демонстрации:

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);
}

это из Memcached, магазин не вызывался:

> 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

И в моем профилировщике SQL он вызвал 3 запроса в течение 3 тестов => Доказано, что объект, вызванный из Memcached, равен нулю, затем запрос.

1 Ответ

2 голосов
/ 24 января 2010

Похоже, что по умолчанию (DefaultTranscoder) используется BinaryFormatter; «однонаправленный» материал - это инструкция для другого сериализатора (DataContractSerializer), а не добавляет [Serializable].

(Примечание: я добавил для себя памятку , чтобы попытаться написать транскодер protobuf-net для memcached; это было бы круто и исправило бы большую часть этого бесплатно )

Я не проверял, но есть несколько вариантов:

  1. написать другую реализацию транскодера, которая обнаружит [DataContract] и использует DataContractSerializer, и подключить этот транскодер
  2. добавить [Serializable] к вашим типам через частичный класс (я не уверен, что это будет работать из-за невозможности сериализации типов полей LINQ)
  3. добавить реализацию ISerializable в частичный класс, который использует DataContractSerializer
  4. как 3, но с использованием protobuf-net, которое a: работает с «однонаправленным», а b: быстрее и меньше DataContractSerializer
  5. написать сериализуемый DTO и сопоставить ваши типы с , что

Последнее простое, но может добавить больше работы.

Мне бы хотелось сначала посмотреть на 3-й вариант, так как 1-й предполагает перестройку провайдера; 4-й вариант также определенно будет в моем списке вещей для тестирования.


Я боролся с 3 из-за того, что DCS возвращал другой объект во время десериализации; Вместо этого я переключился на protobuf-net, так что вот версия, которая показывает добавление partial class к существующему типу [DataContract], что позволяет работать с BinaryFormatter. На самом деле, я подозреваю (с доказательствами), что это также сделает его намного более эффективным (чем необработанный [Serializable]), а также:

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);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...