Question

Sorry for my english, I'll do it as well as I can.

I have the Entity "Usuario" which receives from the rbacManager the object, calling Login method (see below). This method, as you can see, throws an exception when it can't match both the user an password. In this case, I have to increment the property Intentos, to allow users to have only three opportunities to fail.

The problem is the following: SaveChanges method is not saving the values modified in Usuario. I think that SaveChanges method is failing due to the exception, but i'm not sure. I couldn't find any help on the web.

This is the action Method LogOn:

using(EntitiesModel dbContext = new EntitiesModel())
        {
            try
            {
                string hPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(model.Password, "SHA1");

                Usuario usuario = this.rbacManager.Login(model.UserName, hPassword);

                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                    && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                {
                    return Redirect(returnUrl);
                }
                else
                    return RedirectToAction("Index", "Home");

            }
            catch (LoginIncorrectoException)
            {
                dbContext.SaveChanges();
                ViewData["Message"] = "User incorrect.";
            }
            catch (UsuarioBloqueadoException)
            {
                ViewData["Message"] = "User locked";
            }

            return View(model);
        }

And the method Login of the fourth line, that throws the exception:

using (EntitiesModel context = new EntitiesModel())
        {
            Usuario usuario = this.GetUsuario(username);

            if (usuario == null)
                throw new LoginIncorrectoException();

            if (!usuario.EstaActivo())
            {
                throw new UsuarioBloqueadoException();
            }

            if (usuario.Password != password)
            {
                usuario.Intentos++;

                if (usuario.Intentos >= 3)
                {
                    usuario.Activo = false;
                    context.SaveChanges();
                    throw new UsuarioBloqueadoException();
                }
                else
                {
                    context.SaveChanges();
                    throw new LoginIncorrectoException();
                }
            }

            usuario.Intentos = 0;

            return usuario;
        }

EDIT: I copy GetUsuario method.

  private Usuario GetUsuario(string username)
    {
        using (EntitiesModel context = new EntitiesModel())
        {
            List<Usuario> Usuarios = context
               .Usuarios
               .Where(x => x.Username == username)
               .ToList();

            if (Usuarios.Count == 1)
                return Usuarios.First();
            else
                throw null;
        }
    }

Anyone knows why SaveChanges is not working? Thanks!

Was it helpful?

Solution

Your problem is with the fact that each method is creating and disposing its own DbContext. So when the GetUser call returns the User object it is detached from the DbContext because you've disposed of it. Changes to that User object will now not be saved. The most immediate fix is to pass the EntitiesModel created in the Login method to the GetUser method. Of course there are better Unit Of Work patterns that you should research and implement, but this should get you across the immediate hurdle. You could also Attach the User object returned by the GetUser call to the EntitiesModel created inside the Login call.

OTHER TIPS

The 'GetUsuario' method is creating it's own context and the context in the 'Login' method has no pending changes since the 'Usuario' object is managed by another context (which has already been disposed).

You should ensure that 'SaveChanges' is called on the same context instance that was used to obtain the object in the first place.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top