0

I am rewriting the ASP.NET Identity user system with Dapper instead of Entity Framework and encountered an issue while creating new user accounts.

We have a user object passed to us by identity that is inserted to a database, however that user object does not yet have the correct Id because Identity can't know what auto-increment the database is up to yet.

So the SQL procedure that inserts the user object also returns all the data of the user that was just inserted, I'll call this returned object retUser.

In C#, if I set the user object in the following way:

user.Id = retUser.Id;

then the Id is changed correctly and the user of the website can proceed as normal.
If I instead set the entire user model in the following way:

user = retUser;

Then C# instead "assigns by value" I assume, and does not actually change the global version of the user object.

Is there a single line assignment in C# that allows me to set the entire user object by reference? Or am I misunderstanding why this is occurring?

Joshua
  • 162
  • 1
  • 2
  • 9
  • 2
    The first example mutates the object referenced by the `user` variable. The second example re-assigns the `user` variable to reference an entirely different object. These are very different things. If you want to mutate the object, use the first example. (As an analogy... Imagine that you have a house and you want to paint it blue. In the first example you give someone your address and they come paint your house blue. In the second example you give someone the address of a house that's already blue as an example. But your house wasn't involved at all.) – David Feb 22 '23 at 14:51
  • 1
    https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref – mxmissile Feb 22 '23 at 14:52
  • So there is no way in base C# to set all the values of the properties in an object to the value of the properties in another object? Thanks for the prompt response. – Joshua Feb 22 '23 at 14:55
  • 1
    @Joshua: There are ways to approach something like that. Making use of reflection to iterate over object properties, using tools like AutoMapper might help, etc. Personally I've yet to encounter a scenario where the simplest and most supportable approach wasn't simply to just write a method that updates the object as needed, property by property. – David Feb 22 '23 at 14:57
  • Yea, I guess I can add a method to our ApplicationUser object that copies over the details of the other user object - was just hoping for a more succinct approach. – Joshua Feb 22 '23 at 15:03
  • 1
    in fact there is "no" concept of a object being passed by VAL. in say vb.net, even if you tag the parameter as by "val", then you STILL passing a pointer anyway, and not a copy of the object. (hence, you can't say even pass a object as "read only" to a method of some other object, since as noted, you only passing a pointer to to the object anyway. And as pointed out, no, there is no built in "method" or some such to make a copy of a object. – Albert D. Kallal Feb 22 '23 at 16:32

2 Answers2

1

Then C# instead "assigns by value" I assume, and does not actually change the global version of the user object.

Assuming user is a class, this would be a reference assignment. I.e. user previously refereed to object A, but now refers to B. Other references might still refer to A, and A remains unchanged. Changing your reference is not the same as updating all the properties of a shared object. There is no built in function for this, but you could write one yourself

public class User{
    public long Id {get; private set;}
    ...
    public void CopyPropertiesFromObject(User other){
        Id = other.Id;
    }
}

You could also add another level of indirection:

public class Ref<T>{
    public T Value {get;set;}
}

That would allow you to change the the reference in a shared object. But it can make the code a bit more difficult to read and understand.

If the problem is limited to the Id, I would just make sure to update the Id after each call. Or just try to reduce sharing of objects, so you can ensure all references actually are updated after the object has been saved.

JonasH
  • 28,608
  • 2
  • 10
  • 23
1

As far as I know dapper does not track the state of objects like EF so it should be perfectly fine to re-assign user with retUser unless you have something else that is tracking the state of user and will not pick up the re-assignment.

YungDeiza
  • 3,128
  • 1
  • 7
  • 32
  • 1
    I think I do have such a case, Identity would likely lose track of the User if I did this. – Joshua Feb 22 '23 at 15:02