Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
316 views
in Technique[技术] by (71.8m points)

c# - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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();
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...