在我的项目(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映射尽可能优雅,有效和高效?
答案 0 :(得分:0)
我发现直接在视图中使用域实体是有问题的。为了帮助解耦,我采用了两种不同的技术。
最重要的是,我使用单独的ViewModel类将数据传递给视图。当数据与域模型实体很好地对应时,AutoMapper可以减轻在它们之间复制数据的痛苦,但是否则需要一些手动布线。看起来在开始时做了很多工作但是一旦项目开始增长就会有所帮助,如果你不是从头开始设计数据库,这一点尤为重要。我还使用中间服务层来获取ViewModel,以保持控制器的精益,并能够重用逻辑。
第二个选项主要是出于性能原因,但我通常最终会创建自定义存储库来获取跨越实体的数据。也就是说,我创建了一个自定义类来保存我感兴趣的数据,然后编写自定义LINQ(或其他)来将结果投影到其中。这通常可以显着提高仅提取实体的性能,并在检索数据后应用投影。
如果我还不够详细,请告诉我。
答案 1 :(得分:0)
我最终实施的解决方案并不能完全满足我,但它现在已经完成了。
我将我的标签/类别划分为“真实实体”,在NHibernate中映射为单独的实体和“引用”,根据它们描述的实体映射为组件。
因此,在我的C#代码中,我有两个单独的类 - TagEntity
和TagReference
,它们都从域视角查看相同的信息。 TagEntity
知道数据库ID并由NHibernate会话管理,而TagReference
仅将标记名称作为字符串,因此在整个应用程序中使用非常方便,如果需要,它仍然可以轻松转换为{{ 1}}使用静态查找字典。
该实体/引用分离允许我以更有效的方式查询数据库,仅加入两个表,例如TagEntity
而不加入select from articles join articles_tags ... where articles_tags.tag_id = X
表,当完全简单时,它也将被连接起来面向对象的NHibernate查询。