【问题标题】:Get existing entity if it exists or create a new one获取现有实体(如果存在)或创建一个新实体
【发布时间】:2010-04-29 20:25:51
【问题描述】:

我正在导入数据库中可能已经存在或不存在的数据。我希望 NHibernate 将任何实体与现有的数据库相关联(如果存在)(可能只是设置主键/ID),或者如果不存在则创建一个新的。我正在为我的框架(MVC 2、NHibernate、Fluent)使用 S#arp 架构。

我已将 [HasUniqueDomainSignature] 属性添加到类中,并将 [DomainSignature] 属性添加到要用于比较的属性中。我能想到的唯一方法(这不是一个可接受的解决方案,甚至可能不起作用)是以下(伪 C#):

foreach (Book importedBook in importedBooks){
    foreach (Author author in importedBook.Authors){
        if (!author.IsValid()){  // NHibernate Validator will check DomainSignatures
            author = _authorRepository.GetByExample(author);  // This would be to get the db object with the same signature, 
                                 //but I don't think I could even update this as I iterate through it.
        }
}

}

如您所见,这既混乱又毫无意义。再加上我在书中有六个关联(主题、格式等),这没有任何意义。必须有一个简单的方法来做到这一点,我错过了。我不是 NHibernate 的新手,但我绝对不是专家。

【问题讨论】:

    标签: nhibernate fluent-nhibernate domain-driven-design s#arp-architecture


    【解决方案1】:

    我可能不理解这个问题,但是数据“可能存在也可能不存在于数据库中”怎么可能?例如,如果一本书有 2 个作者,如果作者不存在,关系如何存储在数据库级别?

    您似乎正在尝试使用 NHibernate 导入您的数据(或创建一个不存在的实体),这似乎不正确。

    【讨论】:

    • 你是对的,我正在尝试使用 NHibernate 导入我的数据。基本上,我有一个系统,其中已经有一些作者(和书籍)。我得到一个包含更多作者(和书籍)的数据源。我想获取该提要并将尚未拥有的书籍/作者导入我的系统。导入中还有很多事情要做,这就是为什么我要转换为域模型并使用 NHibernate 导入(而不是仅仅将其保存在数据集中并使用 ADO 导入数据。这可能吗?
    • 我猜这是可能的,但我不知道该怎么做。我的建议是使用不同的工具进行导入。
    【解决方案2】:

    大多数数据库实现都支持条件 UPDATE-or-INSERT 语法。例如,Oracle 有一个MERGE command。结合映射中的 Hibernate <sql-insert> 块,您应该能够解决问题。我不知道 Fluent,但我认为它也支持这一点。

    【讨论】:

      【解决方案3】:

      只是意识到我从未给出答案或批准他人的答案。我最终只写了一个新的 SaveOrUpdate ,它需要一个参数来在持久化之前检查是否存在。我还在我的域模型中添加了一个属性,以便在保存/更新时覆盖(尽管回想起来它只是在更新时才会被覆盖)。

      如果它可以帮助其他人在这个困境中,这是代码:

             public TEntity SaveOrUpdate<TEntity>(TEntity entity, bool checkForExistingEntity)
          {
              IRepository<TEntity> repository = new Repository<TEntity>();
              if (checkForExistingEntity) {
      
                  if (entity is Entity) {
                      IEnumerable<PropertyInfo> props = (entity as Entity).GetSignatureProperties();
                      Dictionary<string, object> parameters =
                          props.ToDictionary(propertyInfo => propertyInfo.Name, propertyInfo => propertyInfo.GetValue(entity, null));
                      TEntity duplicateEntity = repository.FindOne(parameters);
                      if (duplicateEntity != null) {
                          // Update any properties with the OverwriteOnSaveUpdate attribute
                          foreach (var property in RepositoryHelper.GetUpdatableProperties(typeof(TEntity)))
                          {
                              object initialValue = property.GetValue(entity, null);
                              property.SetValue(duplicateEntity, initialValue, null);
                          }
                          // Fill in any blank properties on db version
                          foreach (var property in typeof(TEntity).GetProperties())
                          {
                              if (property.GetValue(duplicateEntity, null) == null) {
                                  object initialValue = property.GetValue(entity, null);
                                  property.SetValue(duplicateEntity, initialValue, null);
                              }
                          }
                          return duplicateEntity;
                      }
                  }
              }
              return SaveOrUpdate(entity);
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-07-05
        • 2011-01-21
        • 1970-01-01
        • 1970-01-01
        • 2021-10-16
        • 1970-01-01
        相关资源
        最近更新 更多