dswatik
dswatik

Reputation: 9209

How would I serialize a LINQ-to-SQL lazy list

I have a linq query and I am trying to put that in to a serializable object for a distributed caching (Velocity) but its failing due to a LINQ-to-SQL lazy list

like so

  return from b in _datacontext.MemberBlogs
                   let cats = GetBlogCategories(b.MemberBlogID)
                   select new MemberBlogs
                   {
                       MemberBlogID = b.MemberBlogID,
                       MemberID = b.MemberID,
                       BlogTitle = b.BlogTitle,
                       BlogURL = b.BlogURL,
                       BlogUsername = b.BlogUsername,
                       BlogPassword = b.BlogPassword,
                       Categories = new LazyList<MemberBlogCategories>(cats)
                   };

LazyList is the same class Rob Conery uses in his MVC storefront...

all three classes are marked serializable (MemberBlogs,MemberBlogCategories,LazyList... any ideas?

Upvotes: 6

Views: 1806

Answers (4)

Jonathan
Jonathan

Reputation: 592

I know this is an old post but I had the same issue as I wanted to execute my LazyList and put them into the AppFabric Cache. I ended up putting some custom serialization logic into the LazyList type.

The first part now looks like this:

 public class LazyList<T> : IList<T>, ISerializable
{

    public LazyList()
    {
        this.query = new List<T>().AsQueryable();
    }

    public LazyList(SerializationInfo info, StreamingContext context)
    {
        try {
            this.inner = (List<T>)info.GetValue("InnerList", typeof(List<T>));
        }
        catch (Exception ex)
        {
            this.inner = null;
        }
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        if (this.inner != null)
            info.AddValue("InnerList", this.inner.ToList());
    }

    public LazyList(IQueryable<T> query)
    {
        this.query = query;
    }

    public LazyList(List<T> l)
    {
        inner = l;
    }
}

Upvotes: 0

Chris Shaffer
Chris Shaffer

Reputation: 32575

I'm just guessing, but I'd say the problem is that it is serializing the query instead of the results; I don't know what the implementation of the LazyList looks like, but you can probably add an OnSerializing method that actually executes the query prior to serializing it; Something like:

[OnSerializing]
private void ExecuteLinqQuery(StreamingContext context)
{
    if (!SomethingThatIndicatesThisLinqQueryHasNotBeenExecuted)
        LinqVariable.ToList()
}

This way you get to keep the Lazy Load (for anything that doesn't go into your cache), but then also if it does hit the cache, it'll execute the linq query and cache the results.

Upvotes: 3

Duncan
Duncan

Reputation: 2503

If you are putting it in a distributed cache you will need to avoid the LazyList altogether. You can then call .ToList() around the whole LINQ statement as in:

(from x select new MemberBlogs).ToList()

This should then be cachable because it forces the queries to be evaluated.

Upvotes: 6

jonnii
jonnii

Reputation: 28322

If you're caching it why are you using a lazy list? Don't use a lazy list, use caching, and the problem goes away.

Upvotes: 2

Related Questions