这是一个关于如何处理ORM模型的一般性问题,必须通过http和tcp传输在应用程序之间传递它们,但是特别是我通过Castle Active Record使用NHibernate,如果它有任何区别。传输上的数据格式可以是JSON,也可以是XML。
在通过传输传递ORM模型时,我遇到了三个问题:
XML / JSON序列化时的循环引用错误。可以通过在关系属性上使用ScriptIgnore和XmlIgnore属性来解决这些错误,但是它不是一个很好的解决方案,因为有时您希望包含被忽略的关系对象,如果删除ignore属性,可能会导致其他地方出现循环引用错误。
序列化时延迟加载。假设您有类A与类B具有1:1的关系。您序列化类A,它将尝试调用db来获取并序列化类B.有时您不再处于允许延迟加载的正确会话中在序列化和抛出错误的点。这也可以使用ignore属性解决,但由于同样的原因,这不是一个好的解决方案。
ORM模型的基类不能序列化为XML,但是是密封的。我不知道这个问题有什么解决办法,但我已多次遇到过。
上述问题的一个解决方案是根本不在传输中来回传递ORM模型,我听过很多人说这是推荐的解决方案。但是,你如何以干净的方式做到这一点?假设您有ModelA,您希望使用某种传输从一个应用程序传递到另一个应用程序。
您创建了一个ModelAView类,它具有ModelA的所有属性,但不包含所有ORM属性,基类和延迟加载功能。解决方案已经不干净,因为您现在有2个具有相同重复属性的类。如果要对模型进行更改,则必须在两个类中进行更改。
您从数据库中获取ModelA实例,并且必须逐个字段填充ModelAView的属性。也许你有一个ModelAView的构造函数,它传递一个ModelA实例,并在那里设置属性,所以它更清洁一点。但是,您仍然需要按属性设置values属性,这可能很麻烦。您可以尝试执行某种克隆功能,但是如果它具有子对象,那么您需要进行深度克隆,并且似乎没有一种好的方法可以做到这一点,特别是因为View类不一定都有与ModelA类相同的属性。
您将ModelAView通过传输传递给其他应用程序。
另一个应用程序希望可以使用ModelAView来完成它需要做的任何事情。但是,如果它需要更新ModelA的属性并将它们保存到db,则需要执行相反的操作,将ModelAView中的所有属性复制到ModelA,然后保存到db。
所以我在这里写了很多,但我希望我已经明确了在这些情况下处理ORM模型时遇到的挑战。有没有人可以分享经验和真实方法来处理这些问题的经验,这些问题不需要代码重复和/或逐个属性地将值从一个对象复制到另一个对象?
答案 0 :(得分:4)
我觉得你运气不好。我遇到了同样的问题(很多人都有)并且共识似乎是你应该使用DTO(数据传输对象)。 AutoMapper让它更容易一些。
如果您使用NH的结果转换器将结果作为DTO返回,您可以省去从实体转换为DTO的麻烦。
我们最终为每个实体创建了几个不同的DTO,每个实体包含不同的子代或集合,例如客户,CustomerWithOrders等需要DTO的客户必须提前知道它需要什么,以便它可以请求正确的类型。
但维护它并不是太糟糕,因为我们的实体没有太大变化。