Глубокая сериализация объектов LINQ to SQL - PullRequest
0 голосов
/ 12 марта 2011

Я пытаюсь сериализовать некоторые объекты, сгенерированные LINQ to SQL для использования с Memcached , если это вообще возможно. Я работаю над новым транскодером, который будет действовать как новый сериализатор для использования с объектами LINQ to SQL.

Кажется, классы DataContractSerializer не пытаются сериализовать реляционные объекты. Например, если бы у меня были эти отношения:

Course -> CourseProject -> Project

Свойства для Course будут сериализованы, но реляционные списки для CourseProject и Project будут пустыми, а не нулевыми. Я почти уверен, что это функция однонаправленной сериализации, чтобы избежать циклических избыточностей.

Вот проблема с этим ... при загрузке элементов из кэша отношения полностью пусты (пусто IEnumerable, а не null) и никогда не будут загружены из базы данных, если будет запрошено. Фактически все проекты курса теряются при извлечении из кэша.

Если бы я мог сериализовать хотя бы один или два уровня глубже, чем базовый объект, это было бы полезно. Если это невозможно, то я бы даже предпочел, чтобы несериализованные данные загружались из базы данных «лениво», хотя подобного рода не идет вразрез с целью сериализации и кэширования.

Ответы [ 2 ]

1 голос
/ 15 марта 2011

Хорошо, после нескольких дней, пока я стучал головой по столу, думаю, я понял это до работоспособного уровня ... было несколько вещей, которые мне действительно нужно было понять сначала:

  1. LINQ to SQL во многом строит свои отношения с помощью отложенной загрузки. Вещи загружаются по требованию.
  2. Существует два контекста сущности: Присоединено и Отделено . В отключенном состоянии изменения объекта не отслеживаются, а отношения не загружаются лениво (так как источник данных не связан с объектом).
  3. Десериализованные объекты всегда отделены , поэтому не будут иметь связанных свойств.

Таким образом, настоящий трюк заключается в том, чтобы просто прикрепить объект (ы), как только вы их десериализовали. Вот реальный пример из нашей системы (у нас есть несколько оболочек memcached для нашей системы).

string cacheKey = "apSpace_GetActiveSpacesForPerson_PersonID:" + personid;
List<apSpace> list = MemCached.Get<List<apSpace>>(cacheKey);
if (list == null)
{
    //Some complex, intensive query...
    list = (from s in BaseDB.apSpaces
            from so in BaseDB.apSpaceOwners
            from sp in BaseDB.apSpacePersons
            where (so.PersonID == personid
            && so.SpaceID == s.SpaceID
            && s.Deleted == false
            && s.IsArchived == false)
            || (sp.PersonID == personid
            && sp.SpaceID == s.SpaceID
            && s.Deleted == false
            && s.IsArchived == false)
            select s).Distinct().OrderBy(s => s.Name).ToList();
    //Cache the query result
    MemCached.Store(cacheKey, list);
}
else
    BaseDB.apSpaces.AttachAll(list); //Attach immediately!

return list;

Очевидно, что это не серебряная пуля в отношении кеширования связанных данных, но она позволяет вам сохранять отношения и в то же время кэшировать первоначальный результат интенсивного запроса. LINQ to SQL будет лениво загружать все после этого независимо от этого.

1 голос
/ 12 марта 2011

Я решил эту проблему, создав универсальную оболочку, которую я использовал для сопоставлений с отложенной загрузкой:

 public class SqlRecord<T>{
     where T: ISqlDataObject

     public TAssociationRecord GetOneToOneAssociation<TAssociationRecord>(Expression<Func<T,TAssociationRecord>>> getAssociationPropertyExpression)
          where TAssociationRecord : ISqlDataObject
     {
     } 

     public IEnumerable<TAssociationRecord> GetOneToManyAssociation(Expression<Func<T,EntitySet<TAssociationRecord>>> getAssociationPropertyExpression)
         where TAssociationRecord: ISqlDataObject
     {
     }

 }

Затем я добавил интерфейс маркера для всех объектов данных, которые были автоматически сгенерированы LINQ to SQL:

  public interface ISqlDataObject {}

Могу поспорить, вы могли бы сделать что-то подобное, чтобы удовлетворить ваши потребности.

...