1

I have the following objects:

 [Serializable]
    public class Module
    {
        [Key]
        public int Id { get; set; }
        public string ModuleName { get; set; }
        public string FontAwesomeClass { get; set; }
    }

   [Serializable]
    public class ModulosPorUsuario
    {
        [Key]
        public int Id { get; set; }
        public string Email { get; set; }
        public virtual ICollection<Module> Modules{ get; set; }
    }

And I am using the method to cache in a specific key for each user its assigned modules.

 /// <summary>
        /// Gets the modules activated for a user
        /// </summary>
        /// <param name="email">Email address of the user</param>
        /// <returns>List of modules for the selected user</returns>
        public static List<Models.ModulosPorUsuario> GetModulesForUser(string identityname)
        {
            /// It needs to be cached for every user because every user can have different modules enabled.
            var cachekeyname = "ApplicationModulesPerUser|" + identityname;

            IDatabase cache = CacheConnectionHelper.Connection.GetDatabase();
            List<Models.ModulosPorUsuario> listOfModulesPerUser = new List<Models.ModulosPorUsuario>();
            listOfModulesPerUser = (List<Models.ModulosPorUsuario>)cache.Get(cachekeyname);
            if (listOfModulesPerUser == null)
            {
                listOfModulesPerUser = dbApp.ModulosPorUsuario.Where(p => p.Email == identityname).ToList();
                cache.Set(cachekeyname, listOfModulesPerUser, TimeSpan.FromMinutes(SettingsHelper.CacheModuleNames));
                return listOfModulesPerUser;
            }
            else
            {
                return listOfModulesPerUser;
            }
        }

The first time its working, of course its returning the data from DB. But the second time, (there is an object on cache), but the list of Modules is null:

http://screencast.com/t/OFB1vkvno

I also have this helper classes from stackexchange redis cache:

public static class SampleStackExchangeRedisExtensions
    {
        public static T Get<T>(this IDatabase cache, string key)
        {
            return Deserialize<T>(cache.StringGet(key));
        }

        public static object Get(this IDatabase cache, string key)
        {
            return Deserialize<object>(cache.StringGet(key));
        }

        public static void Set(this IDatabase cache, string key, object value, TimeSpan expiration)
        {
            cache.StringSet(key, Serialize(value), expiration);
        }

        static byte[] Serialize(object o)
        {
            if (o == null)
            {
                return null;
            }
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            using (MemoryStream memoryStream = new MemoryStream())
            {
                binaryFormatter.Serialize(memoryStream, o);
                byte[] objectDataAsStream = memoryStream.ToArray();
                return objectDataAsStream;
            }
        }

        static T Deserialize<T>(byte[] stream)
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            if (stream == null)
                return default(T);

            using (MemoryStream memoryStream = new MemoryStream(stream))
            {
                T result = (T)binaryFormatter.Deserialize(memoryStream);
                return result;
            }
        }
    }

I know there is data related because of the SEED:

 #region Seed Modules
            var module1 = new Module() { Id = 1, ModuleName = "Contabilidad", FontAwesomeClass = "fa-ambulance" };
            var module2 = new Module() { Id = 2, ModuleName = "Recursos Humanos", FontAwesomeClass = "fa-heartbeat" };
            var module3 = new Module() { Id = 3, ModuleName = "Inventario", FontAwesomeClass = "fa-anchor" };
            var module4 = new Module() { Id = 4, ModuleName = "Produccion", FontAwesomeClass = "fa-binoculars" };
            var module5 = new Module() { Id = 5, ModuleName = "Produccion", FontAwesomeClass = "fa-binoculars" };
            var module6 = new Module() { Id = 6, ModuleName = "Ventas", FontAwesomeClass = "fa-coffee" };
            var module7 = new Module() { Id = 7, ModuleName = "Compras", FontAwesomeClass = "fa-calendar-o" };
            var module8 = new Module() { Id = 8, ModuleName = "Cotizaciones", FontAwesomeClass = "fa-building" };
            context.Modulos.Add(module1);
            context.Modulos.Add(module2);
            context.Modulos.Add(module3);
            context.Modulos.Add(module4);
            context.Modulos.Add(module5);
            context.Modulos.Add(module6);
            context.Modulos.Add(module7);
            context.Modulos.Add(module8);

            context.SaveChanges();
            #endregion

  #region Seed ModulosPor Usuario
            context.ModulosPorUsuario.Add(new ModulosPorUsuario()
            {
                Id=1,
                Email = "companyadmin@mysaasapp.onmicrosoft.com",
                Modules = new List<Module>() { module1, module2 }
            });

            context.ModulosPorUsuario.Add(new ModulosPorUsuario()
            {
                Id=2,
                Email = "accountingadmin@mysaasapp.onmicrosoft.com",
                Modules = new List<Module>() { module3, module5 }
            });

            context.ModulosPorUsuario.Add(new ModulosPorUsuario()
            {
                Id=3,
                Email = "jayhamlin@mysaasapp.onmicrosoft.com",
                Modules = new List<Module>() { module4, module6 }
            });

            context.ModulosPorUsuario.Add(new ModulosPorUsuario()
            {
                Id=4,
                Email = "usuario1@mysaasapp.onmicrosoft.com",
                Modules = new List<Module>() { module7, module7 }
            });


            context.SaveChanges();
            #endregion

Update1:

This is the error I get when I try to get the cached value the 2nd time:

An exception of type 'System.Runtime.Serialization.SerializationException' occurred in mscorlib.dll but was not handled in user code

Additional information: Unable to find assembly 'EntityFrameworkDynamicProxies-Inspinia_MVC5, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

stack trace

   at System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly()
   at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name)
   at System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
   at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
Luis Valencia
  • 32,619
  • 93
  • 286
  • 506

1 Answers1

3

I believe you need to create an empty constructor for this type (see code snippet below) and instantiate your collection. The Serialization engine will not do it for you and it will expect that that collection is instantiated.

Further, since your collection property is an interface and not a class, the Serializer is probably getting confused when trying to initialize this property and add items.

public class ModulosPorUsuario
{
    // added this constructor
    public ModulosPorUsuario()
    {
        this.Modules = new List<Module>();
    }        

    [Key]
    public int Id { get; set; }
    public string Email { get; set; }
    public virtual ICollection<Module> Modules { get; set; }
}

Though you are initializing it before you serialize, the Serializer is instantiating objects on your behalf when you deserialize.

Happy Coding.

Glenn Ferrie
  • 10,290
  • 3
  • 42
  • 73
  • I thought that maybe ICollection was not serializable, so I changed to List, but that didnt fix the problem, testing the constructor now – Luis Valencia Jul 03 '15 at 16:26
  • any other idea @Glenn Ferrie – Luis Valencia Jul 03 '15 at 17:06
  • It looks like an assembly is missing, based on the screencast you provided. where is that DLL? – Glenn Ferrie Jul 03 '15 at 17:20
  • found this: but all assemblies are there. its autogenerated apparently http://completedevelopment.blogspot.com/2010/09/aspnetmvcentity-framework-error-unable.html – Luis Valencia Jul 03 '15 at 17:28
  • You're on the right path. Unless you generate serialization assemblies at build time they are always generated at run-time which (a) causes a downgrade in perf and (b) can cause problems if the user context that the app is running in doesnt have write access to the disk. My advice would be to generate the serialization assemblies at build. you should see settings in the csproj file (Project Settings) – Glenn Ferrie Jul 03 '15 at 17:31
  • csproj is a huge file and by looking at it, its unclear how to generate serialization assemblies at build. – Luis Valencia Jul 03 '15 at 17:33
  • (1) you dont edit that file you edit the project properties from within VS. (2) you can also use a tool called SGEN to get it done. here's a link: http://stackoverflow.com/questions/9187248/when-to-change-the-generate-serialization-assembly-value – Glenn Ferrie Jul 03 '15 at 18:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/82327/discussion-between-glenn-ferrie-and-esteban-v). – Glenn Ferrie Jul 03 '15 at 18:25