How do I access DbContext.Entry<TEntity> Method (TEntity) in my generic repository class?

3.2k views Asked by At

This should be really obvious but for some reason I can't figure it out. So in my generic repository class I have an update method to update an entity:

public void Update<TEntity>(TEntity entity) where TEntity : class, IBusinessEntity
{
    try
    {
        if (entity == null)
        {
            throw new ArgumentNullException("entity");
        }
        TEntity existing = _context.Set<TEntity>().Find(entity.Id);
        if (existing != null)
        {
            _context.Entry(existing).CurrentValues.SetValues(entity);
            this._context.SaveChanges();
        }
    }
    catch (DbEntityValidationException dbEx)
    {
        var msg = string.Empty;
        foreach (var validationErrors in dbEx.EntityValidationErrors)
        {
            foreach (var validationError in validationErrors.ValidationErrors)
            {
                msg += Environment.NewLine + string.Format("Property: {0} Error: {1}",
                validationError.PropertyName, validationError.ErrorMessage);
            }
        }
        var fail = new Exception(msg, dbEx);
        throw fail;
    }
}

The problem is I get an error on this line:

_context.Entry(existing).CurrentValues.SetValues(entity);

I get a red squiggly under Entry and the error reads

IBusinessEntityContext does not contain a definition for 'Entry' and no extension method 'Entry' accepting a first argument of type IBusinessEntityContext could be found (are you missing a using directive or an assembly reference?)

Here is my IBusinessEntityContext class:

namespace ContentManager.Employees.EF
{
    using System.Data.Entity;
    using Models.Employees;

    public interface IBusinessEntityContext
    {
        DbSet<TEntity> Set<TEntity>() where TEntity : class, IBusinessEntity;

        int SaveChanges();
    }
}

I have a bunch of using statements at the top of my repository class:

namespace ContentManager.Employees.EF
{
    using System;
    using System.Data.Entity.Validation;
    using System.Linq;
    using System.Reflection;
    using System.Data.Entity;
    using Models.Employees;
    using Models.Employees.EF;
    using System.Data.Entity.Infrastructure;

    public class EFEmployeeEntityRepository : IEFEmployeeEntityRepository
    {
        // bunch of code
    }
}

Here is the documentation for DbContext.Entry Method (TEntity). It says that the namespace is just System.Data.Entity, which I am using. As you can see from the code above this repository implements IEFEmployeeEntityRepository. The code for that in case it's necessary is below:

namespace ContentManager.Employees.EF
{
    using System.Linq;
    using Models.Employees.EF;

    public interface IEFEmployeeEntityRepository: IEmployeeEntityRepository
    {

        IQueryable<TEntity> BeginQuery<TEntity>() where TEntity : EFBusinessEntity;
    }
}

This class extends IEmployeeEntityRepository, so the code for that is here:

public interface IEmployeeEntityRepository
{
    TEntity GetById<TEntity>(Guid id) where TEntity : class, IBusinessEntity;
    void Insert<TEntity>(TEntity entity) where TEntity : class, IBusinessEntity;
    void Update<TEntity>(TEntity entity) where TEntity : class, IBusinessEntity;
    void Delete<TEntity>(TEntity entity) where TEntity : class, IBusinessEntity;
}

Does anyone know why I can't use the Entry method? The documentation says that the method is just

public DbEntityEntry<TEntity> Entry<TEntity>(
    TEntity entity
)
where TEntity : class

so I wonder if I could just write this method in myself? But then I'm worried the other methods in that line (namely, CurrentValues.SetValues(entity)) won't work either. Alternatively, is that line even necessary? The tutorial that I got the code from wrote the update method with just

this._context.SaveChanges();

but I felt like that doesn't do anything, so I added in

_context.Entry(existing).CurrentValues.SetValues(entity);

But I am not sure if this is right.

1

There are 1 answers

0
jjj On BEST ANSWER

The problem is that in your Update method, all the compiler knows is _context is of type IBusinessEntityContext and the compiler has no idea that _context has type DbContext somewhere in its inheritance tree. You could add this to your interface:

public interface IBusinessEntityContext
{
    DbSet<TEntity> Set<TEntity>() where TEntity : class, IBusinessEntity;

    int SaveChanges();

    // Add this
    DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class, IBusinessEntity;
}