Otro: no se puede crear un valor constante de tipo

Cada vez que creo que estoy entendiendo estas cosas.

Error completo:

No se puede crear un valor constante de tipo 'Models.staffnames'. Solo se admiten tipos primitivos ('como Int32, String y Guid') en este contexto.

Versiones: .Net 4 EF 4

Creo que tiene algo que ver con que DU y db.UserProfiles sean Enumerables, pero cuando trato de empujarlo hacia atrás para que todo sea IQueryable, todo explota. Tal como está ahora, el error se produce al crear la lista de soporte.

Es interesante notar que la única vez que este problema parece surgir es cuando estoy trabajando con el proveedor de Roles. Que en el pasado simplemente lo descargué en un bucle for.

Cualquier ayuda sería apreciada.

Código:

IEnumerable<MembershipUser> du = Roles.GetUsersInRole("Dealer").Select(u => Membership.GetUser(u)).AsEnumerable();
        IQueryable<staffnames> du_up = du.Join(db.UserProfiles.AsEnumerable(), mu => (Guid)mu.ProviderUserKey, up => up.UserID, (mu, up) => new staffnames
        {
            UserId = (Guid)mu.ProviderUserKey,
            FirstName = up.FirstName,
            LastName = up.LastName
        }).AsQueryable();
        List<MemberSupportModel> support = db.Wins_support.Where(s=>s.dealerid == uid && !s.closed).Select(s=> new MemberSupportModel{
             aeramanagerack = s.aeramanagerack,
             amgrname = du_up.Where(a => a.UserId == s.aeramanger).Select(a=>a.FirstName+" "+a.LastName).FirstOrDefault(),
             aeramangerackdate = s.aeramangerackdate,
             atypedesc = _atype.Where(wt => wt.Value == s.atypeid).Select(wt => wt.Description).FirstOrDefault(),
             wtypedesc = _wtype.Where(wt => wt.Value == s.typeid).Select(wt => wt.Description).FirstOrDefault(),
             comment =s.comment,
             dateSubmitted = s.dateSubmitted,
             vdate =s.vdate,
             venuename = s.Venues_Logs.Venue.venueName           
        }).ToList();

preguntado el 27 de julio de 12 a las 15:07

1 Respuestas

El problema es la linea amgrname = du_up.Where(... porque du_up es una colección de un tipo no primitivo en memoria, de ahí la excepción. AsQueryable no ayuda aquí, en memoria está en memoria, no puedes cambiar eso.

Intentaría cargar los datos que necesita de la base de datos por separado y luego fusionar su du_up collection con la colección de datos cargados desde la base de datos:

// LINQ to Objects in memory
IEnumerable<MembershipUser> du = Roles.GetUsersInRole("Dealer")
    .Select(u => Membership.GetUser(u));

// LINQ to Objects in memory
// db.UserProfiles.AsEnumerable() loads whole UserProfiles table from DB
IEnumerable<staffnames> du_up = du.Join(db.UserProfiles.AsEnumerable(),
    mu => (Guid)mu.ProviderUserKey, up => up.UserID, (mu, up) => new staffnames
    {
        UserId = (Guid)mu.ProviderUserKey,
        FirstName = up.FirstName,
        LastName = up.LastName
    });

// LINQ to Entites = database query
List<MemberSupportModel> support = db.Wins_support
    .Where(s=>s.dealerid == uid && !s.closed)
    .Select(s=> new // anonymous result object
    {
        aeramanagerack = s.aeramanagerack,
        aeramanger = s.aeramanger, // needed later for the du_up Where clause
        aeramangerackdate = s.aeramangerackdate,
        atypedesc = _atype.Where(wt => wt.Value == s.atypeid)
                          .Select(wt => wt.Description)
                          .FirstOrDefault(),
        wtypedesc = _wtype.Where(wt => wt.Value == s.typeid)
                          .Select(wt => wt.Description)
                          .FirstOrDefault(),
        comment = s.comment,
        dateSubmitted = s.dateSubmitted,
        vdate = s.vdate,
        venuename = s.Venues_Logs.Venue.venueName
    })
    .AsEnumerable() // execute database query
    // now LINQ to Objects in memory again
    // Copy values from anonymous result object and select data from du_up
    .Select(s => new MemberSupportModel
    {
        aeramanagerack = s.aeramanagerack,
        amgrname = du_up.Where(a => a.UserId == s.aeramanger)
                        .Select(a => a.FirstName + " " + a.LastName)
                        .FirstOrDefault(),
        aeramangerackdate = s.aeramangerackdate,
        atypedesc = s.atypedesc,
        wtypedesc = s.wtypedesc,
        comment = s.comment,
        dateSubmitted = s.dateSubmitted,
        vdate = s.vdate,
        venuename = s.venuename
    })
    .ToList();

Respondido 27 Jul 12, 16:07

Gracias una vez más Slauma. Eso parece mucho trabajo para obtener un nombre del perfil de usuario, ¿tal vez este podría ser un caso en el que un proceso almacenado sería una mejor llamada? - Chris

Además, ¿no sería una mala práctica cargar toda la tabla de perfiles de usuario desde la base de datos? ¿O es una cuestión de preferencia? - Chris

@Chris: a menos que escriba un proceso almacenado, realmente no tiene una alternativa para cargar la tabla de perfil desde la base de datos porque las tablas de membresía de ASP.NET no son parte de su modelo EF, por lo que no puede escribir ningún LINQ para Entidades consultas que unen su modelo EF con las tablas de pertenencia. Yo diría: si no tiene problemas de rendimiento y la tabla UserProfiles no es enorme y no se espera que sea enorme con el tiempo, siga con el enfoque anterior, de lo contrario: Stored Proc. - Slauma

@Saluma al revisar el diseño, pensé demasiado en el objetivo y en realidad no tenía necesidad de hacer referencia al modelo de membresía. Pero el aprendizaje adicional fue una ventaja, así que todo salió bien. También agregué un campo bool IsStaff a la tabla de perfil de usuario que limitará la atracción. De nuevo, gracias por tu ayuda. - Chris

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.