0

Hello I'm trying to create a generic repository pattern class that uses 2 generics in its implementation. The entity type itself (TEntity) and the key/identifier type (TKey).

Problem occurs whenever I try to check for equality of TKey's.

Error: Operator '==' cannot be applied to operands of type 'TKey' and 'TKey'.

Entity.cs

public class Entity<TKey> where TKey : struct, IComparable, IFormattable, IConvertible, IComparable<TKey>, IEquatable<TKey>
{
    public TKey Id { get; set; }
}

IRepository.cs

public interface IRepository<TEntity, in TKey> : IDisposable 
        where TEntity : Entity<TKey> 
        where TKey : struct, IComparable, IFormattable, IConvertible, IComparable<TKey>, IEquatable<TKey>
    {
        /// <summary>
        /// Get the <typeparamref name="TEntity"/> by id.
        /// </summary>
        /// <returns>The entity.</returns>
        /// <param name="id">Identifier.</param>
        TEntity Get(TKey id);
    }

Repository.cs

public class NoSQLRepository<TEntity, TKey> : IRepository<TEntity, TKey> 
        where TEntity : Entity<TKey> 
        where TKey : struct, IComparable, IFormattable, IConvertible, IComparable<TKey>, IEquatable<TKey>
    {    
        public TEntity Get(TKey id)
        {
            // error occurs in the line below.
            return _context.Get<TEntity>(typeof(TEntity).Name).Find(entity => entity.Id == id).FirstOrDefault();
        }
    }

This being said, I need my TKey generic to not be constrained to a class. I rather use primitive types (i.e Int).

Can this be achieved or am I doing something wrong ?

xRed
  • 1,895
  • 6
  • 20
  • 36
  • Does `.Equals()` work? – Robert Harvey Feb 11 '19 at 20:05
  • Haven't tried it, but it compiles. Does it use the default equality comparer automatically if I use for example an Int ? – xRed Feb 11 '19 at 20:15
  • @xRed just to be clear on your comment: it sounds like you are asking "if I call `Int32.Equals` method will it call `Int32.Equals` method or something else" which is confusing at least... You may want to clarify your comment... – Alexei Levenkov Feb 11 '19 at 20:21
  • Yes, it does. See for example [Int32.Equals](https://learn.microsoft.com/en-us/dotnet/api/system.int32.equals?view=netframework-4.7.2), which implements IEquatable. – Robert Harvey Feb 11 '19 at 20:22
  • `entity => entity.Id.Equals(id)` will use `IEquatable.Equals(TKey other)` (from the generic constraint). Whether this works at runtime depends on the query provider. – Ivan Stoev Feb 11 '19 at 20:27
  • @RobertHarvey The code is getting translated into SQL, not run, so the behavior of the code if it were actually run is irrelevant. Not all query providers will match the equality semantics of C# when translating. – Servy Feb 11 '19 at 20:56
  • @Servy: Those are some pretty broad assumptions, given the code in the OP. There's no indication of SQL translation of any kind occurring there, and the OP did not tag their question [tag:entity-framework]. – Robert Harvey Feb 11 '19 at 21:19
  • @RobertHarvey It's an assumption, but it's a pretty safe assumption, given all of the names of things and code shown. You're assuming that this is an `IEnumerable`, and that this is not a query provider, and there's much *less* of a basis for that assumption over mine. If you want to ask the OP specifically to clarify and be explicit about it then by all means. – Servy Feb 11 '19 at 21:30
  • Thanks all for the feedback. I have in fact 2 implementations, one for SQL using EntityFrameworkCore (which already works) and another for NoSQL (using the official C# MongoDb driver) which I can't test at the moment but will try tomorrow! – xRed Feb 11 '19 at 21:54

0 Answers0