How to use AsNoTracking when working with Repository

0

I have a generic repository and I have a Controllers for each of my entities.

eventoContactIdOcorrenciaRecebida = dtoEventoContactId.ObterPorCodigoEvento(Convert.ToInt32(codigoEventoContactID));

When I do the search it returns the value correctly, however if for some reason I change the value in the bank, and do the search again it does not update. It's like she's looking in the cache, not the bank. If I close the application and open it again it does the search correctly. From what I researched here on vi I understood that I have to use AsNotracking() . But how can I use it in this command line above.

I'll edit here by putting more information

The eventContacIdOurCredit is an instance of Model ContactIDEvent

The dtoEventoContactId is the Controllers

Controllers:

public class ContactIDEventoControllers : Repository<ContactIDEvento>, IContactIDEvento
{
    public ContactIDEvento ObterPorCodigoEvento(int intCodigo)
    {
        return Buscar(c => c.Codigo == intCodigo).FirstOrDefault();
    }
}

Template:

public class ContactIDEvento
{
    public int ContactIDEventoID { get; set; }
    public int Codigo { get; set; }
    public string Nome { get; set; }
}

Interface Repository

public interface IRepository<TEntity> : IDisposable where TEntity : class
{
    TEntity Adicionar(TEntity obj);

    TEntity ObterPorId(int id);

    IEnumerable<TEntity> ObterTodos();

    TEntity Atualizar(TEntity obj);

    void Remover(int id);

    IEnumerable<TEntity> Buscar(Expression<Func<TEntity, bool>> predicate);

    int SaveChanges();
}

Repository

public abstract class Repository<TEntity> : IRepository<TEntity> where TEntity: class
{
    protected MonitoramentoContext Db;
    protected DbSet<TEntity> DbSet;

    public Repository()
    {
        Db = new MonitoramentoContext();
        DbSet = Db.Set<TEntity>();
    }

    public TEntity Adicionar(TEntity obj)
    {
        var objAdd = DbSet.Add(obj);
        SaveChanges();
        return objAdd;
    }

    public TEntity Atualizar(TEntity obj)
    {

        var entry = Db.Entry(obj);
        DbSet.Attach(obj);
        entry.State = EntityState.Modified;

        SaveChanges();
        return obj;
    }

    public IEnumerable<TEntity> Buscar(Expression<Func<TEntity, bool>> predicate)
    {
        return DbSet.Where(predicate);
    }

    #region IDisposable Support
    private bool disposedValue = false; // To detect redundant calls

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects).
            }

            // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
            // TODO: set large fields to null.

            disposedValue = true;
        }
    }

    // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
    // ~Repository() {
    //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
    //   Dispose(false);
    // }

    // This code added to correctly implement the disposable pattern.
    public void Dispose()
    {
        // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        Dispose(true);
        // TODO: uncomment the following line if the finalizer is overridden above.
        GC.SuppressFinalize(this);
    }
    #endregion

    public TEntity ObterPorId(int id)
    {
        return DbSet.Find(id);
    }

    public IEnumerable<TEntity> ObterTodos()
    {
        return DbSet.ToList();
    }

    public void Remover(int id)
    {
        DbSet.Attach(DbSet.Find(id));
        DbSet.Remove(DbSet.Find(id));
        SaveChanges();
    }

    public int SaveChanges()
    {
        return Db.SaveChanges();
    }
}
    
asked by anonymous 22.09.2017 / 14:17

1 answer

1

I believe you are encapsulating the Find method of EF behind this ObterPorCodigoEvento method.

If this is the case, there is no AsNoTracking for Find, what you can do is:

// Estou chutando que a assinatura do seu método é esta, 
// se não for, a parte importante mesmo é o novo parâmetro 'asNoTracking'

public object ObterPorCodigoEvento(object id, bool asNoTracking = false)
{
   var entity = Context.Entidade.Find(id);

   if(asNoTracking)
   {  
      // Isso não deixa rastrear o objeto.
      Context.Entry(entity).State = EntityState.Detached;
   }

   return entity;
}

If you're using Where in the entire collection:

public object ObterPorCodigoEvento(object id, bool asNoTracking = false)
{
   return asNoTracking ? Context.Entidade.Where(t => t.Id == id).AsNoTracking().FirstOrDefault()
                       : Context.Entidade.Where(t => t.Id == id).FirstOrDefault();
}

In your case it would look like this:

Repository Interface

IEnumerable<TEntity> Buscar(Expression<Func<TEntity, bool>> predicate, bool asNoTracking);

Repository

public IEnumerable<TEntity> Buscar(Expression<Func<TEntity, bool>> predicate, bool asNoTracking = false)
{
    return asNoTracking ? DbSet.Where(predicate).AsNoTracking()
                        : DbSet.Where(predicate);
}

Then just adjust the code that is calling the repository in your Controller to pass the boolean parameter asNoTracking .

Controller

public class ContactIDEventoControllers : Repository<ContactIDEvento>, IContactIDEvento
{
    public ContactIDEvento ObterPorCodigoEvento(int intCodigo)
    {
        // O true quer dizer que você quer o AsNoTracking
        return Buscar(c => c.Codigo == intCodigo, true).FirstOrDefault();
    }
}
    
22.09.2017 / 14:29