Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DbSet doesn't have a Find method in EF7

I am trying to create a generic repository to access my database. In EF6 I was able to do that in order to get a specific entity:

protected IDbSet<T> dbset;  public T Get(object id) {     return this.dbset.Find(id); } 

DbSet in EF7 is missing a Find method. Is there a way to implement the above piece of code?

like image 360
Lyudmil Dimitrov Avatar asked Mar 13 '15 10:03

Lyudmil Dimitrov


People also ask

Is DbSet part of DbContext?

Definition. A DbSet represents the collection of all entities in the context, or that can be queried from the database, of a given type. DbSet objects are created from a DbContext using the DbContext.

What is the difference between DbSet and DbContext?

Intuitively, a DbContext corresponds to your database (or a collection of tables and views in your database) whereas a DbSet corresponds to a table or view in your database. So it makes perfect sense that you will get a combination of both!

How do I get a DbSet?

You can get DbSet from DbContext by Type using the method DbContext. Set(Type entityType) . So if you have the model class name as string you should do some mapping to actual clr type.

What is DbSet in Entity Framework Core?

In Entity Framework Core, the DbSet represents the set of entities. In a database, a group of similar entities is called an Entity Set. The DbSet enables the user to perform various operations like add, remove, update, etc. on the entity set.


2 Answers

Here's a very crude, incomplete, and untested implementation of .Find() as an extension method. If nothing else, it should get you pointed in the right direction.

The real implementation is tracked by #797.

static TEntity Find<TEntity>(this DbSet<TEntity> set, params object[] keyValues)     where TEntity : class {     var context = ((IAccessor<IServiceProvider>)set).Service.GetService<DbContext>();      var entityType = context.Model.GetEntityType(typeof(TEntity));     var key = entityType.GetPrimaryKey();      var entries = context.ChangeTracker.Entries<TEntity>();      var i = 0;     foreach (var property in key.Properties)     {         var keyValue = keyValues[i];         entries = entries.Where(e => e.Property(property.Name).CurrentValue == keyValue);         i++;     }      var entry = entries.FirstOrDefault();     if (entry != null)     {         // Return the local object if it exists.         return entry.Entity;     }      // TODO: Build the real LINQ Expression     // set.Where(x => x.Id == keyValues[0]);     var parameter = Expression.Parameter(typeof(TEntity), "x");     var query = set.Where((Expression<Func<TEntity, bool>>)         Expression.Lambda(             Expression.Equal(                 Expression.Property(parameter, "Id"),                 Expression.Constant(keyValues[0])),             parameter));      // Look in the database     return query.FirstOrDefault(); } 
like image 144
bricelam Avatar answered Oct 09 '22 08:10

bricelam


In case you are using EF 7.0.0-rc1-final, below you find a small update for the code presented by @bricelam in the previous answer. By the way, thank you very much @bricelam - your code was extremely useful for me.

Here are my dependencies under "project.config":

"dependencies": {     "EntityFramework.Commands": "7.0.0-rc1-final",     "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",     "Microsoft.Framework.Configuration.Json": "1.0.0-beta8",     "Microsoft.Framework.ConfigurationModel": "1.0.0-beta4",     "Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",     "Microsoft.Framework.DependencyInjection": "1.0.0-beta8" } 

And below is the extension method for DbSet.Find(TEntity):

using Microsoft.Data.Entity; using Microsoft.Data.Entity.Infrastructure; using System; using System.Linq; using System.Linq.Expressions;  namespace Microsoft.Data.Entity.Extensions {     public static class Extensions     {         public static TEntity Find<TEntity>(this DbSet<TEntity> set, params object[] keyValues) where TEntity : class         {             var context = ((IInfrastructure<IServiceProvider>)set).GetService<DbContext>();              var entityType = context.Model.FindEntityType(typeof(TEntity));             var key = entityType.FindPrimaryKey();              var entries = context.ChangeTracker.Entries<TEntity>();              var i = 0;             foreach (var property in key.Properties)             {                 entries = entries.Where(e => e.Property(property.Name).CurrentValue == keyValues[i]);                 i++;             }              var entry = entries.FirstOrDefault();             if (entry != null)             {                 // Return the local object if it exists.                 return entry.Entity;             }              // TODO: Build the real LINQ Expression             // set.Where(x => x.Id == keyValues[0]);             var parameter = Expression.Parameter(typeof(TEntity), "x");             var query = set.Where((Expression<Func<TEntity, bool>>)                 Expression.Lambda(                     Expression.Equal(                         Expression.Property(parameter, "Id"),                         Expression.Constant(keyValues[0])),                     parameter));              // Look in the database             return query.FirstOrDefault();         }     } } 
like image 27
Roger Santana Avatar answered Oct 09 '22 06:10

Roger Santana