Repository pattern return element in only read

Viewed 42

I realized that if I call the SelectById method and then I modify the variable and commit, the changes are applied to the database, so the update method is totally useless. I wanted to avoid doing such a thing, since anyone with access to the pattern Repository can modify variables without going through the update method. What I want is to be able to return a variable that is "detached" from the database and if you were to commit the changes are not applied. I was able to do this only in the following way, inside the selectByID, I create a new dataset and then do the dispose.

sensor repository constructor

       public SensorRepository(OramsContext _db, ILogger logger) : base(_db, logger)
        {
            _context = _db;
        }

Method with new context

        public override  Sensor? SelectByID(int id)
        {
            // new context
            var internaContext = _context;
            
             var query = (from x in internaContext.Sensor where x.SensorId == id select x).FirstOrDefault();
            
            //dispose after query
            internaContext.Dispose();
            
             if (query == null)
            {
                return null;
            }
            return query;
        }

if I do this, in case of changing the variable and then calling the Complete, the value is not updated

        using (UintOfWork uow = new UintOfWork())
        {
            Sensor? s =  uow.Sensors.SelectByID(10);
            if (s != null)
            {
                s.ReferenceIdFile = 100+i;
                int c = await uow.CompleteAsync();
            }


        }

This is a classic Select method found online, In this case, if I modify the variable and save without passing the update, the changes are saved in the DB.

        public override Sensor? SelectByID(int id)
        {

            return (from x in dbSet where x.SensorId == id select x).FirstOrDefault();
        }

What I am wondering is if there is a better way to do as I did in the method with the new Context.

UPDATE

and if I had to put two contexts, one only view and the other for the action of update, insert and delete?

These are the two context variables


        private readonly OramsContext _context;


        private readonly OramsContext _contextView;

In the selectByID method I use the "view-only" context

        public async Task< Sensor?> SelectByIDAsync(int id)
        {
            return await (from x in _contextView.Sensor where x.SensorId == id select x).FirstOrDefaultAsync();
        }

And in the Complate method,I invoke SaveChangese only on the other one

        public async Task<int> CompleteAsync()
        {
            try
            {
                return await _context.SaveChangesAsync();
            }
            catch (Exception ex)
            {

                _logger.LogError(ex, "{Repo} CompleteAsync method error", typeof(UintOfWork));
                return 0;
            }

        }

Can this system have problems?

1 Answers

You can use .AsNoTracking() which detaches the entity returned from your context. Any changes you make aren't tracked by the EF entitytracker.

return (from x in dbSet.AsNoTracking() where x.SensorId == id select x).FirstOrDefault();
Related