-1

I have many entities that use a UserId property of the same type.

Can I define a type (string or int, ...) that I can easily change as a variant for all?

Example:

public class Entity_One
{
    public DefineMyType UserId { get; set; }
    public string Property_Entity_One { get; set; }
}

public class Entity_Two
{
    public DefineMyType UserId { get; set; }
    public string Property_Entity_Two { get; set; }
}

const DefineMyType = string;
// or const DefineMyType = int;
// or const DefineMyType = Guid;
  • 1
    It can to be an id or not. example: in table User, it is id; in another table, it is foreign key. If I edit type of UserId in User (string to int), I must edit all relation table. So, I want define a DefineMyType. Then If edit type of UserId in User, I only edit DefineMyType – Kenny Tran Aug 07 '21 at 03:47
  • why not ? have you tried? – Serg Shevchenko Aug 07 '21 at 13:29

1 Answers1

0

Constants can't be used like that.

Preprocessor may be used.

But we can use a generic:

public abstract class AbstractID<T>
{
  static protected T Last = default;
  public T Value { get; protected set; } // or perhaps init only with C# 9
}

Thus we can define some specialized IDs like:

public class NumberID<T> : AbstractID<T> where T : struct, IComparable, IFormattable
{
  public NumberID()
  {
    Value = (T)( (dynamic)Last + 1 );
    Last = Value;
  }
}

public class GuidID : AbstractID<Guid>
{
  public GuidID()
  {
    Value = Guid.NewGuid();
    Last = Value;
  }
}

public class StringID : AbstractID<string>
{
  private string Generate()
  {
    return ...
  }
  public StringID()
  {
    Value = Generate();
    Last = Value;
  }
}

Then we can set the "default" ID type:

public class ManagedID : NumberID<int>
{
}

Or:

public class ManagedID : GuidID
{
}

Therefore we can easily change ManagedID for all code using it.

It only requires to change the ancestor class in the declaration.

And now that works:

public class EntityOne
{
  public ManagedID UserId { get; } = new ManagedID();
  public string PropertyEntityOne { get; set; }
}

public class EntityTwo
{
  public ManagedID UserId { get; } = new ManagedID();
  public ManagedID EntityOneId { get; }
  public string PropertyEntityTwo { get; set; }
  public EntityTwo(EntityOne one)
  {
    EntityOneId = one.UserId;
  }
}

Test

var entity1 = new EntityOne();
var entity2 = new EntityOne();
var entity3 = new EntityTwo(entity1);
Console.WriteLine(entity1.UserId.Value);
Console.WriteLine(entity2.UserId.Value);
Console.WriteLine(entity3.UserId.Value + $" ({entity3.EntityOneId.Value})");

Result with an integer

1
2
3 (1)

Result with a GUID

3a189122-60fd-4dc5-9d7f-3cc4c83375f9
37a9c7de-8ed5-4d02-a1b9-f414db051335
2de962d6-cc91-4e78-b3dc-28acb0ba7f3b (3a189122-60fd-4dc5-9d7f-3cc4c83375f9)

Warning

Here, the use of numbers is very basic and not really reliable, especially beyond a local machine and after stopping the execution of the current process. Thus persistence somewhere of the last value is required for a real database, like in a config file or whatever.

GUID vs INT IDENTITY

Guid vs INT - Which is better as a primary key?

Int for identity/primary key and Guid for public identifier, best practices?