Extending IdentityUser with nullable foreign key to another IdentityUser

I’m working on a framework which builds on .net core Identity. Let’s say I wanted to extend the IdentityUser<TKey> class with a ParentUserId property while the developer should still be able to decide which type to use for the TKey primary key. This property would be a foreign key to another user, but could be null if the user doesn’t have a parent.

Using string for TKey would work without problems because strings are nullable and don’t conflict with the where TKey : IEquatable<TKey> constraint (although I don’t know why). But if the developer decides to use int, I’m screwed.

Currently I’m thinking about a solution like this:

public class FrameworkUser<TKey, TNullableKey> : IdentityUser<TKey>         where TKey : IEquatable<TKey> {     public virtual TNullableKey ParentUserId { get; set; }      // for better understanding     public virtual FrameworkUser<TKey, TNullableKey> ParentUser { get; set; } } 

But I’m very unsure and don’t think it’s beautiful.

  1. The developer could do something like new FrameworkUser<string, int?>() by mistake. Would be great if something like where TNullableKey : Nullable<TKey> were possible.

  2. I can’t constraint TNullableKey. IEquatable doesn’t allow nullable value types (i.e. int?), although I don’t know if this will result in worse performance when used as a foreign key anyway. struct won’t allow strings.

  3. Getting the value of ParentUserId will differ depending on the type. For instance to securely get the value of an int?, I would check for int?.HasValue to be true and then get it’s value from int?.Value. The same procedure is quite different for a string which could be null, empty, or have some chars. This would make switches from one type to another without extra work difficult/impossible.

Another solution could be having two implementations, one for string and one for struct, but that’s not feasible because then I would also need to have two IdentityStore<TUser>s and so on.

So, what would you do?