0

I want to add a Guid identifier to a few of my entities.

My initial approach was to make it the Primary Key for those entities. But that seems to make the rest of my code more complex.

For example we must now allow for multiple ID types in the generic repository and specify the PK type for each DbEntity (code samples below).

Therefore I am considering maintaining a consistent int PK on all entities, and adding the Guid as an additional property when required. This also means that I don't have to worry about ensuring the Guid is not used as a clustering key.

Simpler code. No cluster worries. The 'additional property' approach looks like a winner to me.

However I don't see it mentioned, used or recommended anywhere. (In comparison there are plenty of articles disussing using a Guid for a PK).

Are there any disadvantages to this approach? Could doing things this way come back and bite me?


Using Only Int as PK

public class DbEntity
{
    [Key]
    public int ID { get; set; }
} 

public class Car : DbEntity
{}

public class House: DbEntity
{}



public virtual T SelectByID(int id, params Expression<Func<T, object>>[] includeExpressions)
{
      var set = includeExpressions.Aggregate<Expression<Func<T, object>>, IQueryable<T>>
                  (table, (current, expression) => current.Include(expression));

      return set.SingleOrDefault(i => i.ID == id);
}

public virtual T SelectByGuid(string guid, params Expression<Func<T, object>>[] includeExpressions)
{
      var set = includeExpressions.Aggregate<Expression<Func<T, object>>, IQueryable<T>>
                  (table, (current, expression) => current.Include(expression));

      return set.SingleOrDefault(i => i.AdditionalGuidProperty == guid);
} 

Using Both Int and Guid as PK

public class DbEntity<PKT>
{
    [Key]
    public PKT ID { get; set; }
} 

public class Car : DbEntity<int>
{}

public class House : DbEntity<guid>
{}



public virtual T SelectByID(PKT id, params Expression<Func<T, object>>[] includeExpressions)
{
      var set = includeExpressions.Aggregate<Expression<Func<T, object>>, IQueryable<T>>
                  (table, (current, expression) => current.Include(expression));

      ParameterExpression parameter = Expression.Parameter(typeof(T), "s");
      PropertyInfo propertyInfo = typeof(T).GetProperty("ID");
      MemberExpression memberExpression = Expression.MakeMemberAccess(parameter, propertyInfo);
      ConstantExpression constantExpression = Expression.Constant(id, typeof(PKT));
      BinaryExpression binaryExpression = Expression.Equal(memberExpression, constantExpression);
      Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(binaryExpression, parameter);

      return set.SingleOrDefault(lambda);
}
Community
  • 1
  • 1
Martin Hansen Lennox
  • 2,837
  • 2
  • 23
  • 64
  • im not writing it as an answer because i dont fill like explanation TOO much, but it's best not to use GUID as ID because the indexing is too heavy and using more resources to filters. what i WOULD suggest is to create entities with int Id and some other GUID to make the convertion. If you are using SQL for example, a good Guid To Id table would be nice OR if you like to store it inside the same object (sql -> row ) its also ok BUT you need to consider that the table will suffer from higher traffic queries (i mentioned it's heavy..) if comment is enough, ill post as answer – Ori Refael Mar 09 '16 at 22:29
  • `Guid` to Id table is a good idea, I might go for that. I'm interested to know whether there is any downside to having a `guid` identifier in addition to an `int` PK. Because it sounds like a good idea... and yet I don't see it done often. On the other hand it IS pretty common to use guids as a PK (e.g. MS do it for Users by default). – Martin Hansen Lennox Mar 10 '16 at 00:21

0 Answers0