Base solution for your next web application
Open Closed

How to use Repository pattern #782


User avatar
0
sampath created

Hi, I have written one of my application layer method as shown below.Here I didn't use repository pattern due to I don't know how to do that by using repository pattern.I know it is not good to use db context directly on the application layer as shown below.And also I have added "Abp.Zero.Entityframework" reference into the Application layer.So all are BAD I think.So could you tell me how to use below mentioned code snippet with the repository pattern ? Thanks.

public async Task<int?> EditPropertyAsync(CreateOrEditPropertyInput input)
        {
            // Load original parent including the child item collection
            var property = await _context.Properties
                    .Where(p => p.Id == input.Property.Id)
                    .Include(p => p.TaxMapLots)
                    .FirstOrDefaultAsync();

            foreach (var child in property.TaxMapLots.ToList())
            {
                _context.TaxMapLots.Remove(child);
            }

            _unitOfWorkManager.Current.SaveChanges();

            input.Property.MapTo(property);
            if (AbpSession.TenantId != null)//set TenantId
            {
                property.TenantId = AbpSession.TenantId.Value;
                property.Address.TenantId = AbpSession.TenantId.Value;
            }

            foreach (var child in property.TaxMapLots.ToList())
            {
                _context.TaxMapLots.Add(child);
            }

            _context.SaveChanges();

            return input.Property.Id;
        }

8 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    You can inject Property repository as you always do. Then you can use _propertyRepository.GetAl() instead of _context.Properties. Rest of the code remains similar, except you will use repository's delete instead of dbcontext's remove.

    This prevents usage of dbcontext in application layer.

    Referencing EF is not so bad since we can not use Include otherwise. If you want to move your code into repository, you need to create a custom repository as described in documents: <a class="postlink" href="http://www.aspnetboilerplate.com/Pages/Documents/EntityFramework-Integration#DocCustomRepositoryMethods">http://www.aspnetboilerplate.com/Pages/ ... oryMethods</a>

  • User Avatar
    0
    sampath created

    Hi, I have changed the code as you mentioned above.But then '_unitOfWorkManager' method is not working. i.e. I need to remove the 'TaxMapLots' records before the final insertion of the 'TaxMapLots'. Could you tell me why ? Thanks.

    var property = await _propertyRepository.GetAll()
                        .Where(p => p.Id == input.Property.Id)
                        .Include(p => p.TaxMapLots)
                        .FirstOrDefaultAsync();
    
                foreach (var taxMapLot in property.TaxMapLots.ToList())
                {
                    _taxMapLotRepository.Delete(taxMapLot);
                }
    
                await _unitOfWorkManager.Current.SaveChangesAsync();//not save this into db here
    
                input.Property.MapTo(property);
    
                foreach (var taxMapLot in property.TaxMapLots.ToList())
                {
                    _taxMapLotRepository.Insert(taxMapLot);
                }
    
  • User Avatar
    0
    sampath created

    Hi Halil, Do you have any feedback for this issue ? Thanks.

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    Actually it should be saved. How did you understand that it's not saved? Have you checked the database if they are deleted? If so, you probably can not see changes since the transaction is not completed yet.

    Also, for your code, I can advice this:

    • You're mapping input.Property to your property entity. Probabably input.Property has a TaxMapLots collection. Mapping such collection has problems with EF as I see before. So, exclude TaxMapLots from mapping (with a custom AutoMap configuration, remove AutoMap attribute) and manually handle input.Property.TaxMapLots (create a TaxMapLot for each then insert into database).
  • User Avatar
    0
    sampath created

    Hi, Actuality when I use "_context" then it woks fine.You can see that on my 1st post.That code is working fine.When I use the repository then it doesn't delete the data after this line " await _unitOfWorkManager.Current.SaveChanges();//not save this into db here".After the run of the above line (on bedbug mode) , I have checked the data row's "Isdeleted" flag.It remains as "false" and if I run further it gives below mentioned error.My sole purpose is to avoid below mentioned error.I don't have any mapping issues here.Hence it is working fine when I use the "_context" (1st post).So what is your thoughts about this strange behaviour ? Thanks.

    The relationship could not 
    be changed because one or more of the foreign-key properties is non-nullable. When 
    a change is made to a relationship, the related foreign-key property is set to a 
    null value.
    
  • User Avatar
    0
    hikalkan created
    Support Team

    I suppose that is related to a soft-delete problem. If you really don't need, you can remove ISoftDelete from your child entity, since soft-delete can be problematic in some cases and it should be carefully used. This is not related to ABP framework. EF removes relations but entity is not deleted actually. Maybe you can try to directly delete children before querying the main entity:

    _taxMapLotRepository.Delete(t => t.PropertyId == input.Property.Id);
    

    as the first line of your method.

  • User Avatar
    0
    sampath created

    Hi, Could you tell me how to do this "If you really don't need, you can remove ISoftDelete from your child entity, since soft-delete can be problematic in some cases and it should be carefully used." ? Thanks.

    Note : Actually I don't need to keep that child entity on "TaxMapLots" table.

  • User Avatar
    0
    hikalkan created
    Support Team

    Then you delete an entity, EF clears foreign key, then delete entity and detach from dbcontext. Then ABP make it 'undeleted' and mark as 'deleted' if it's soft delete, but can not re-bind foreign key. So, EF may throw exception in that case.