4

I want to retrieve multiple records by giving array of primary key and I have to make generic method of it for all the entities.

private DbSet<TEntity> _entities;
      /// <summary>
            /// Get entity by identifier
            /// </summary>
            /// <param name="id">Identifier</param>
            /// <returns>Entity</returns>
            public virtual TEntity GetById(object id)
            {
                return Entities.Find(id);
            }




 /// <summary>
        /// Get entity by identifier
        /// </summary>
        /// <param name="id">Identifier</param>
        /// <returns>Entity</returns>
        public virtual List<TEntity> GetByIds(int id[])
        {
               // want to make it generic
            return Entities.Where(x=>id.Contains(id));
        }

    /// <summary>
        /// Gets an entity set
        /// </summary>
        protected virtual DbSet<TEntity> Entities
        {
            get
            {
                if (_entities == null)
                    _entities = _context.Set<TEntity>();

                return _entities;
            }
        }

problem here is that my Entities doesn't have ID columns, for eg Product has ProductId, Order has OrderId. I don't want to change my db columns to Id.

Entities.Where(x=>id.Contains(id));

I want my entities columns to be same as they are now. can I achieve a generic search method with this db structure to find multiple records?

  • 1
    Possible duplicate of [EntityFramework 6 How to get identity-field with reflection?](https://stackoverflow.com/questions/25141955/entityframework-6-how-to-get-identity-field-with-reflection) – Marco Apr 26 '19 at 12:36
  • 1
    Or, embrace the fact that the `DbSet` already _is_ a generic repository? – Jesse de Wit Apr 26 '19 at 12:38
  • Not another generic repository. DbConext is the unit of work and DbSet is the repository. – William Xifaras Apr 26 '19 at 14:49
  • @Fabio No, it doesn't. `Find` accepts *single* PK consisting of one or more values (in case of composite PK). – Ivan Stoev Apr 27 '19 at 12:56
  • hi @IvanStoev Note warning: This API supports the Entity Framework Core infrastructure and is not intended to be used directly from your code. This API may change or be removed in future releases. https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.metadata.internal.entitytype.findprimarykey?view=efcore-2.1#Microsoft_EntityFrameworkCore_Metadata_Internal_EntityType_FindPrimaryKey – jerrythomas38 Aug 07 '19 at 06:42

2 Answers2

5

You can use EF Core provided metadata services like FindEntityType and FindPrimaryKey to get the PK property name. Then you can use it to access the PK value inside LINQ to Entities query using another EF Core provided useful method EF.Property.

Something like this:

public virtual List<TEntity> GetByIds(int[] ids)
{
    var idName = _context.Model.FindEntityType(typeof(TEntity))
        .FindPrimaryKey().Properties.Single().Name;
    return Entities
        .Where(x => ids.Contains(EF.Property<int>(x, idName)))
        .ToList();
}
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • hi @IvanStoev what are the performance implications of doing it this way? Does .FindPrimaryKey().Properties. cause a schema lock on database table in trying to find primary key? Does it cause any application slowness? What if we create partial classes to auto generate the Ids? What are the advantages /disadvantages in each method performance wise ? Thank you https://stackoverflow.com/questions/57261804/net-core-create-generic-repository-interface-id-mapping-for-all-tables-auto-cod – jerrythomas38 Aug 07 '19 at 01:29
  • posted question here, https://stackoverflow.com/questions/57386900/generic-repository-primary-id-key-performance – jerrythomas38 Aug 07 '19 at 04:20
  • Note warning: This API supports the Entity Framework Core infrastructure and is not intended to be used directly from your code. This API may change or be removed in future releases. https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.metadata.internal.entitytype.findprimarykey?view=efcore-2.1#Microsoft_EntityFrameworkCore_Metadata_Internal_EntityType_FindPrimaryKey – jerrythomas38 Aug 07 '19 at 06:42
  • @jerrythomas38 You are looking at the wrong method documentation (the internal class implementation). The correct link is https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.metadata.ientitytype.findprimarykey?view=efcore-2.1#Microsoft_EntityFrameworkCore_Metadata_IEntityType_FindPrimaryKey. All the methods used in the answer are public. – Ivan Stoev Aug 07 '19 at 06:51
  • greatl ! thanks I would love to get your opinion also on the performance question also https://stackoverflow.com/questions/57386900/generic-repository-primary-id-key-performance – jerrythomas38 Aug 07 '19 at 07:00
3

You can have different names in your application model and your database model. You will have to map your Model Ids to the name in database:

In your Mapping you will have something similar to this for every entity: this.Property(t => t.Id).HasColumnName("ProductId");

xrodas
  • 466
  • 2
  • 10