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?
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.
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!
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.
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.
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(); }
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(); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With