nhibernate - 使用 DTO 时,Automapper 和 Nhibernate 反射(reflect)正在更新的域对象中 DTO 子集合的变化

标签 nhibernate dns automapper dto

我不是很熟悉这个设计,但我希望能得到一些指导。

我有一个后端服务,可以将 DTO 发送到 WPF 智能客户端。在 WPF 智能客户端上,用户将更改、删除和修改项目,然后将更改发回(客户端 --> 服务器)。例如,目前我正在处理客户详细信息表单,用户可以在数据网格中添加、删除和更改属于客户的类别。当 DTO 被发送回服务器时,我想加载与 DTO 中的 ID 相关的域对象,并将对 DTO 所做的更改应用到域对象,包括所有子集合。

我已经尝试在下面的代码中使用 UpdateCustomer 方法做类似的事情。但是,我认为我离题太远了。当代码运行时,我得到的不是 {Individual,Company,NGO,Government} 列表,而是 {Individual,B2B,Company,NGO,Government} 因为它显然没有从原始列表中删除 B2B 条目。

我想到的一个选择是遍历 DTO 集合并将其与域对象的集合进行比较,然后根据已修改的内容添加、删除和更新。然而,这似乎真的很麻烦。

我需要做什么才能将 DTO 的更改应用到我的域对象中的子集合?

非常感谢您的任何帮助,我们将不胜感激

亚历克斯

    public class Customer
        {
            public virtual int Id { get; set; }
            public virtual IList<Category> Categories { get; private set; }
            public virtual string Code { get; set; }
            public virtual string Description { get; set; }

            public Customer()
            {
                Categories = new List<Category>();
            }

            public virtual void AddCategory(string categoryName)
            {
                Categories.Add(new Category(categoryName));
            }
        }

        public class Category
        {

            public virtual string CategoryName { get; private set; }
            public virtual Customer Customer {get;set;}
            public virtual int Id { get; set; }

            protected Category(){}

            public Category(string name)
            {
                CategoryName = name;
            }
        }
    }

    public void SetUpAutoMapper()
    {
        Mapper.CreateMap<Category, CategoryDto>();
        Mapper.CreateMap<Customer, CustomerDto>();
        Mapper.CreateMap<CategoryDto, Category>();
        Mapper.CreateMap<CustomerDto, Customer>();
        Mapper.AssertConfigurationIsValid();
    }
       public void SaveCustomer()
        {
            var customer = new Customer{Code="TESTCUST",Description="TEST CUSTOMER"};
             customer.AddCategory("Individual");
             customer.AddCategory("B2B");
             customer.AddCategory("Healthcare");
             customer.AddCategory("NGO");
             repository.Save(customer);
        }

     public CustomerDto GetCustomer(int customerId)
     { 
        var customer = repository.GetCustomer(customerId);
        var customerDto = Mapper.Map<Customer,CustomerDto>(customer);
        return customerDto;
     }

    public void UpateCustomer(CustomerDto customerToUpdate)
    {
        /*imagine that the dto incoming has had the following operations performed on it
        -----add new category----
        customerToUpdate.Categories.Add(new CategoryDto {CategoryName = "Government"});
        ---update existing category---
        customerToUpdate.Categories[2].CategoryName = "Company";
        ---remove category---
        customerToUpdate.Categories.RemoveAt(1);*/

        var customer = repository.GetCustomer(customerToUpdate.Id);
        /* How in this bit do I ensure that the child collection changes are
        propogated into the underlying customer object retrieved from the database*/
        var customer = Mapper.Map<CustomerDto,Customer>(customerToUpdate);
        repository.Save(customer);
    }

public class CustomerDto
    {
        public int Id { get; set; }
        public string Code { get; set; }
        public string Description { get; set; }
        public List<CategoryDto> Categories { get; set; }
    }

    public class CategoryDto
    {
        public int Id { get; set; }
        public string CategoryName { get; set; }
    }

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
      <class name="Customer" table="Customer">
        <id name="Id" column="CustomerId">
          <generator class="native"/>
        </id>
        <property name="Code" />
        <property name="Description" />
        <bag name="Categories" table="Categories" cascade="all" inverse="false">
          <key column="FK_CustomerID" />
          <one-to-many class="Category"/>
        </bag>
      </class>

      <class name="Category" table="Categories">
        <id name="Id" column="CategoryId">
          <generator class="native"/>
        </id>
        <many-to-one name="Customer" column="FK_CustomerId" not-null="true" class="Customer"></many-to-one>
        <property name="CategoryName" />
      </class>
    </hibernate-mapping>

最佳答案

我最近做了类似的事情,但使用 EF 作为数据层。我不知道 nhibernate 是否知道相同的方法是否有效。

基本步骤是

  • 确保目标集合从数据库加载并附加到对象图以进行更改跟踪
  • .ForMember(dest => dest.Categories, opt => opt.UseDestinationValue())
  • 然后创建一个自定义 IObjectMapper,用于将 IList<> 映射到 IList,其中 T:实体
  • 自定义 IObject 映射器使用了来自 http://groups.google.com/group/automapper-users/browse_thread/thread/8c7896fbc3f72514 的一些代码

    foreach (var child in source.ChildCollection)
    { 
        var targetChild = target.ChildCollection.SingleOrDefault(c => c.Equals(child)); // overwrite Equals or replace comparison with an Id comparison
        if (targetChild == null)
        { 
            target.ChildCollection.Add(Mapper.Map<SourceChildType, TargetChildType>(child));
        } 
        else
        { 
            Mapper.Map(child, targetChild);
        } 
    } 
    
  • 最后一个逻辑是检查 targetCollection 中的所有 Id 是否存在于 sourceCollection 中,如果不存在则将其删除。

最终并没有那么多代码,并且可以在其他操作中重复使用。

关于nhibernate - 使用 DTO 时,Automapper 和 Nhibernate 反射(reflect)正在更新的域对象中 DTO 子集合的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9739568/

相关文章:

nhibernate - NHibernate 的优点和缺点是什么?

nhibernate - 如何将 Fluent NHibernate Automapping 与实体中的多个相同类型的列表一起使用?

java - 使用部分域名的 JNDI DNS 查找

c# - AutoMapper IDataReader 将默认值映射到实体

c# - NHibernate 自动将我的对象更新到数据库,而无需在 Asp.Net MVC 中调用 SaveOrUpdate

.net - 使用 nHibernate 调用存储过程

windows - 如何在 Windows 上配置用户特定的主机文件

azure - 邮件服务器 : using same domain but other hosting

c# - 从服务层返回包含多个实体的 DTO 对象

c# - 将 CreateMap 和 Map 的实例版本与 WCF 服务一起使用?