Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get DB generated IDs back when using repository pattern?

In my solution I have a Domain project and a DataAccess project. My Domain project contains domain objects and interfaces for various repositories and an interface for a UnitOfWork which will contain all my repositories. My DataAccess project contains the implementations of all these interfaces and the EF versions of my Domain objects.

So if I have a class called Person and I want to add a Person to the DB it would look like this:

unitOfWork.People.Add(person);
unitOfWork.Complete();

Inside unitOfWork.People.Add(person) I map my domain Person object to my EF Person object with AutoMapper. Then I add my EF Person object to the EF DbContext object.

public void Add(Person person) {
  DataAccess.Entities.Person dbPerson = Mapper.Map<DataAccess.Entities.Person>(person);
  dbContext.People.Add(dbPerson);
}

The Complete() function just wraps SaveChanges().

public int Complete() {
  dbContext.SaveChanges();
}

Normally EF updates an inserted object's DB generated ID after insertion. But in this case EF knows nothing about my Domain Person object.

Since my Domain Person object doesn't have it's ID, I can't update the DB entry or re-fetch it from the database.

The only alternative I can think of is generating a guid on the server and using that as an ID. But this creates redundancy in the form of two IDs. It also isn't very user friendly since users will reference this ID in search fields. Remembering ID 135 is much simpler than remembering a guid.

Is there some way to get dbContext to update the domain object's ID directly or alternatively have the ID bubble up through the layers?

like image 304
Legion Avatar asked Apr 26 '16 14:04

Legion


People also ask

What problem does repository pattern solve?

In essence, the Repository design pattern facilitates de-coupling of the business logic and the data access layers in your application with the former not having to have any knowledge on how data persistence would actually take place.

How does repository pattern work?

The idea behind the Repository pattern is to decouple the data access layer from the business access layer of the application so that the operations (such as adding, updating, deleting, and selecting items from the collection) is done through straightforward methods without dealing with database concerns such as ...

Should domain objects have ids?

Ids in domain entities is a design smell. In most cases, they indicate poor entity encapsulation. If you want proper separation of concerns, you should reduce the number of Ids in your domain entities to as low as possible.


1 Answers

You can try something like this.

Repository

public class GenericRepository<TEntity> where TEntity : class
{
    internal DbContext context;
    internal DbSet<TEntity> dbSet;

    public GenericRepository(DbContext context)
    {
        this.context = context;
        this.dbSet = context.Set<TEntity>();
    }
    public virtual TEntity Insert(TEntity entity)
    {
        dbSet.Add(entity);
        return entity;
    }
}

Use it like this

 var uow = new UnitOfWork();
 var added = uow.StudentReposiotry.Insert(new Student
 {
    Name = "Repository",
    RegistrationNo = "BSE-2018-004",
    Date = DateTime.Now,
    Department = "Philosphy",
    Email = "test@"
 });
 uow.Save(); //if its saved.
 long id = added.Id;

I added a separate layer called DataProvider which help to keep my entities live only in Repository everything came from DataProvider speaks about DTO.

public class StudentDataProvider : DataProviderBase
{
     public StudentDto Insert(Student dto)
     { 
         var entity = new Student{ Name = dto.Name,Deparment= dto.Deparment};

         var addedItem = unitofwork.StudentReposiotry.Insert(entity);
         unitofWork.Save();

         dto.Id = addedItem.Id;
         return dto;
     }

     public StudentDto AddAndUpdate(StudentDto dto, StudentDto updateDto)
     { 
         var entity = new Student{ Name = dto.Name,Deparment= dto.Deparment};
         var update= new Student{ Name = updateDto.Name,Deparment= updateDto.Deparment};

         var addedItem = unitofwork.StudentReposiotry.Insert(entity);
         var updateItem=  unitofwork.StudentReposiotry.Update(update)
         unitofWork.Save();

         dto.Id = addedItem.Id;
         return dto;
     }
}

 public class DataProvideBase
{
    protected IUnitOfWork UnitOfWork;

    public DataProvideBase()
    {
        UnitOfWork = new UnitOfWork();
    }
}
like image 145
Eldho Avatar answered Sep 22 '22 16:09

Eldho