【问题标题】:How do I get DB generated IDs back when using repository pattern?使用存储库模式时如何取回数据库生成的 ID?
【发布时间】:2016-04-26 14:42:49
【问题描述】:

在我的解决方案中,我有一个域项目和一个 DataAccess 项目。 My Domain 项目包含各种存储库的域对象和接口,以及包含我所有存储库的 UnitOfWork 的接口。我的 DataAccess 项目包含所有这些接口的实现以及我的 Domain 对象的 EF 版本。

因此,如果我有一个名为 Person 的类,并且我想将 Person 添加到数据库中,它将如下所示:

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

unitOfWork.People.Add(person) 内部,我使用 AutoMapper 将我的域 Person 对象映射到我的 EF Person 对象。然后我将我的 EF Person 对象添加到 EF DbContext 对象。

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

Complete() 函数只是包装了 SaveChanges()。

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

EF 通常会在插入后更新插入对象的数据库生成 ID。但在这种情况下,EF 对我的 Domain Person 对象一无所知。

由于我的域人员对象没有它的 ID,我无法更新数据库条目或从数据库中重新获取它。

我能想到的唯一选择是在服务器上生成一个 guid 并将其用作 ID。但这会以两个 ID 的形式产生冗余。它也不是非常用户友好,因为用户会在搜索字段中引用此 ID。记住 ID 135 比记住 guid 简单得多。

有没有办法让 dbContext 直接更新域对象的 ID,或者让 ID 通过层冒泡?

【问题讨论】:

  • 使用 (服务器端生成) Guid 作为主键怎么样?
  • 为什么Add() 返回无效?为什么它不调用 Complete() 并返回插入的 Person 及其生成的 ID(以及可能的其他计算属性)?另见blog.ploeh.dk/2014/08/11/cqs-versus-server-generated-ids
  • 为什么要使用单独的域类?为什么不让 EF 生成域类并持久化它们?
  • @JeroenvanLangen 当人们不得不谈论 Person f1936cfe-69ea-4c50-8dd1-e6bf31e53ff9 时,这对用户不友好。使用小整数要容易得多。我可以同时使用这两种方法,并且只向用户显示数据库生成的 ID,但现在我有重复和额外的行程来重新获取插入的对象。
  • 在将更改提交到数据库后,如果您选择了作为标识(自动增量)的列,只需检查 dbPerson.Id 即可获取已保存实体的 ID。或者您可以在保存更改之前生成您的 ID 使用 GUID 或任何您喜欢的自定义 ID 生成器。

标签: c# entity-framework


【解决方案1】:

你可以试试这样的。

存储库

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

这样使用

 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;

我添加了一个名为 DataProvider 的单独层,这有助于使我的实体仅在存储库中存在,所有来自 DataProvider 的内容都涉及 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();
    }
}

【讨论】:

    【解决方案2】:

    您可以在另一个类似问题中查看我的分析器,因为 UnitofWork 与存储库模式密切相关。

    希望对你有帮助:

    How to get id from Add using UnitOfWork pattern?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-27
      • 2011-09-20
      • 1970-01-01
      • 2014-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多