复杂分类法ORM映射 - 寻找建议

时间:2011-02-09 20:38:32

标签: orm nhibernate-mapping

在我的项目(ASP.NET MVC + NHibernate)中,我有我的所有实体,比如Document,由一组自定义元数据描述。元数据包含在一个可以包含多个标签,类别等的结构中。这些术语对于寻求所需文档的用户来说最为重要,因此它对视图以及底层数据结构,数据库查询等都有影响。

从应用程序的角度来看,我最感兴趣的是术语的字符串值。理想情况下,我想直接操作字符串集合:

class MetadataAsSeenInViews
{
    public IList<string> Categories;
    public IList<string> Tags;
    // etc.
}

从模型的角度来看,我可以使用相同的结构,进行最简单的ORM映射,并在查询中使用它,例如“使用与此类似的元数据获取所有文档”。

但是,如果应用程序需要执行复杂的数据库查询,例如“获取所有文档,至少一个类别为IN (cat1, cat2, ..., catN) ,那么这种结构可能会变得毫无用处或至少一个标签为IN (tag1, ..., tagN)“。在这种情况下,出于性能原因,我们可能会使用数字键作为类别和标签。

因此可以想象一个与MetadataAsSeenInViews相对的结构,它对数字键进行操作,并提供整数到字符串和其他方式的复杂映射。但是,由于以下几个原因,该解决方案并不能让我满意:

  • 它有点像单一责任违规,因为我们在想要描述Document业务对象时处理特定于数据库的问题
  • 数据库密钥正在通过所有层泄漏
  • 在视图中增加了不必要的复杂性
  • 并且我相信它没有利用ORM做的好事

理想情况下,我希望:

  • 单一,尽可能简单的元数据结构(理想情况下就像我的整个应用程序中的那个)
  • 仅在数据库层中解决的复杂查询问题(意味着DB + ORM +尽可能少地为数据层添加代码)

您是否有任何想法如何构建代码并使ORM​​映射尽可能优雅,有效和高效?

2 个答案:

答案 0 :(得分:0)

我发现直接在视图中使用域实体是有问题的。为了帮助解耦,我采用了两种不同的技术。

最重要的是,我使用单独的ViewModel类将数据传递给视图。当数据与域模型实体很好地对应时,AutoMapper可以减轻在它们之间复制数据的痛苦,但是否则需要一些手动布线。看起来在开始时做了很多工作但是一旦项目开始增长就会有所帮助,如果你不是从头开始设计数据库,这一点尤为重要。我还使用中间服务层来获取ViewModel,以保持控制器的精益,并能够重用逻辑。

第二个选项主要是出于性能原因,但我通常最终会创建自定义存储库来获取跨越实体的数据。也就是说,我创建了一个自定义类来保存我感兴趣的数据,然后编写自定义LINQ(或其他)来将结果投影到其中。这通常可以显着提高仅提取实体的性能,并在检索数据后应用投影。

如果我还不够详细,请告诉我。

答案 1 :(得分:0)

我最终实施的解决方案并不能完全满足我,但它现在已经完成了。

我将我的标签/类别划分为“真实实体”,在NHibernate中映射为单独的实体和“引用”,根据它们描述的实体映射为组件。

因此,在我的C#代码中,我有两个单独的类 - TagEntityTagReference,它们都从域视角查看相同的信息。 TagEntity知道数据库ID并由NHibernate会话管理,而TagReference仅将标记名称作为字符串,因此在整个应用程序中使用非常方便,如果需要,它仍然可以轻松转换为{{ 1}}使用静态查找字典。

该实体/引用分离允许我以更有效的方式查询数据库,仅加入两个表,例如TagEntity而不加入select from articles join articles_tags ... where articles_tags.tag_id = X表,当完全简单时,它也将被连接起来面向对象的NHibernate查询。