2

as I wrote in title, I have this code:

public class ApplicationUser : IdentityUser
{
    public virtual MapPosition MapPosition { get; set; }

    public ApplicationUser()
    {
        MapPosition = new MapPosition { PositionX = 0, PositionY = 0 };
    }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public DbSet<MapPosition> MapPositions { get; set; }

    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

And in my controller I have method that I call from @Ajax.ActionLink in my view:

public string ChangeXPosition()
    {
        var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
        // Get the current logged in User and look up the user in ASP.NET Identity
        currentUser = manager.FindById(User.Identity.GetUserId());
        currentUser.MapPosition.PositionX++;

        //manager.Update(currentUser);
        Debug.WriteLine("currentUser.MapPosition.PositionX: " + currentUser.MapPosition.PositionX);

        return "currentUser.MapPosition.PositionX: " + currentUser.MapPosition.PositionX;
    }

I want to save to database changed value of currentUser.MapPosition.PositionX. I have found numerous ways to solve this problem, but none of them worked with my project.

I tried those solutions:

how-to-update-identityuser-with-custom-properties-using-mvc5-and-entity-framewor

updating-user-data-asp-net-identity

mvc5-applicationuser-custom-properties

UPDATE Ok so I tried to do as you said, but still doesn't work:

public class ApplicationUser : IdentityUser
{
    public virtual MapPosition MapPosition { get; set; }

    public ApplicationUser()
    {
    }
}

This version works, my controller method does change the value in the table. But it works only for user, that have been already created. When I create a new User, his new MapPositions record is not created.

public class ApplicationUser : IdentityUser
{
    private MapPosition _mapPosition;
    public virtual MapPosition MapPosition
    {
        get { return _mapPosition ?? (_mapPosition = new MapPosition()); }
    }

    public ApplicationUser()
    {
    }
}

This version doesn't work at all, doesn't change the value in database and doesn't create record in MapPositions when new user is created.

Community
  • 1
  • 1
user3662546
  • 87
  • 12
  • Please describe what are the approaches, which you have tried and which not worked for your case. – Deilan Jun 25 '15 at 22:54

1 Answers1

4

At least you have to invoke SaveChanges method on the current ApplicationDbContext instance after updating the entity instance's fields/properties (currentUser.MapPosition.PositionX in your case):

public string ChangeXPosition()
    {
        var dbContext = new ApplicationDbContext();
        var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(dbContext));
        // Get the current logged in User and look up the user in ASP.NET Identity
        currentUser = manager.FindById(User.Identity.GetUserId());
        currentUser.MapPosition.PositionX++;

        //manager.Update(currentUser);
        Debug.WriteLine("currentUser.MapPosition.PositionX: " + currentUser.MapPosition.PositionX);
        dbContext.SaveChanges();
        return "currentUser.MapPosition.PositionX: " + currentUser.MapPosition.PositionX;
    }

If it does not help, then you have to explicitly mark the corresponding entry as Modified in the DbContext's change tracker in the following way:

dbContext.Entry(currentUser.MapPosition).State = EntityState.Modified;

After that the change should occur in a database as you can see by manually checking the data in the corresponding table at the database (by using Visual Studio SQL Server Data Tools extension, SQL Server Management Studio or any other database management tool).

Deilan
  • 4,740
  • 3
  • 39
  • 52
  • With the addition of this dbContext.Entry it works, value changes in database. But no idea why, each time I invoke this method, it starts again with 0 (and changing it to one)... – user3662546 Jun 25 '15 at 23:16
  • @user3662546, I suppose it's because you are explicitly instantiating `MapPosition` in the constructor of `ApplicationUser` class, so it is not pulled from the database even if lazy loading enabled. Check the part about reference properties of [this answer](http://stackoverflow.com/a/20773057/3095779) on SO. So I suggest you to remove that initialization from the constructor's code. – Deilan Jun 25 '15 at 23:25
  • I tried to do as you instructed, but still doesn't work. Maybe (probably) I did something wrong. – user3662546 Jun 26 '15 at 12:26