zzzprojects / GraphDiff

GraphDiff is a library that allows the automatic update of a detached graph using Entity Framework code first.
https://entityframework-graphdiff.net/overview
MIT License
333 stars 102 forks source link

Using GraphDiff for updating entities #125

Closed cryo75 closed 9 years ago

cryo75 commented 9 years ago

I have a WebApi2 project with EF6 CodeFirst. I'm also using AutoMapper to map between my models and dto's. I use Unit of Work and Repository patterns with Service pattern.

I can update my domain entities in separate ways:

  1. Through controllers (map from dto to model and save)
  2. Through other services

An example of a simple controller action is:

    public Task<IHttpActionResult> Update(int id, CustomerDto customerDto)
    {
        var entity = customerService.Get(id);

        entity.Number = customerDto.Number;
        entity.Description = customerDto.Name;

        entity = customerService.Save(entity);

        return Ok<CustomerDto >(Mapper.Map<CustomerDto >(entity));
    }

And the customerService just calls repository.Update like this:

    public virtual void Update(T entity)
    {
        DbEntityEntry dbEntityEntry = dataContext.GetEntry(entity);
        if (dbEntityEntry.State == EntityState.Detached)
        {
            dbSet.Attach(entity);
            dbEntityEntry.State = EntityState.Modified;
        }
    }

This works fine, however I have complex entities and I would like to use GraphDiff.

My questions are:

  1. Should I still need to load an entity and set its individual properties before updating?
  2. How would I repository Update method look like if I use GraphDiff?
vaclav-antosik commented 9 years ago

Hello, 1.Should I still need to load an entity and set its individual properties before updating?

Answer: I don't see additional value using GraphDiff and REST together. GraphDiff is about updating object trees. I would try to avoid object trees in REST. I see advantage while using SOAP and trees of DTOs. In this scenario I would transfer the whole state of the entity to client and back after user update. Then I would map the DTOs tree to EF's POCO tree and call _context.UpdateGraph to synchronize the state of my detached tree with EF's context.

2.How would I repository Update method look like if I use GraphDiff? dataContext.UpdateGraph(entity)

cryo75 commented 9 years ago

Thanks for the reply.

Yes. Your explanation is similar to what I will be doing. I will load the data using EF, map to DTOs using Automapper (nearly 1-to-1 mapping) and the client will have the whole object tree. Then the client will send back the updated DTO object tree.

When the client sends back the updated object tree, what are the correct steps to map and attach the back to the model?

  1. Map DTOs to new EF POCOs (using automapper)
  2. Attach POCOs to EF context
  3. Call UpdateGraph

Will UpdateGraph load the entity tree automatically from the DB before updating or should I do that manually before step 1?

vaclav-antosik commented 9 years ago

Hi, the flow could be (when the client sends back the updated object tree DTOs): 1, Contract check + validations of arriving DTO tree 2, Map DTO tree to EF POCOs tree (e.g. using automapper) 3, Call dbContext.UpdateGraph - no entity preloading needed

Note: Using this approach you can handle two scenarios = save new and update existing You can have "save entity" method like this:

if (entity.Id == Guid.Empty) { context.Entities.Add(entity); } else { context.UpdateGraph(entity); }

context.SaveChanges();

cryo75 commented 9 years ago

What is no entity preloading needed? Does GraphDiff do the loading itself before updating?

ghost commented 9 years ago

Hi,

yes, GraphDiff loads the currently saved object tree from the database to compare the updated one against it.