NHibernate-错误的思维?基于连接的子类模型

NHibernate-错误的思维?基于连接的子类模型,nhibernate,nhibernate-mapping,Nhibernate,Nhibernate Mapping,我有一个简单的模型类(Part),它从单个表(t_Part)中提取信息 我想要这个模型的一个子类(ProducedPart),它仍然使用NHibernate的缓存机制,但只能是在名为“t_PartProduction”的表中具有外键关系的(Part)的实例。我不需要第二张桌子的模型 我只需要ProducedPart的只读版本 我总是可以在这上面实现一个Facade/Repository,但我希望在NH请求“ProducedPart”时设置一个映射,将“t_Part”与“PartProductio

我有一个简单的模型类(Part),它从单个表(t_Part)中提取信息

我想要这个模型的一个子类(ProducedPart),它仍然使用NHibernate的缓存机制,但只能是在名为“t_PartProduction”的表中具有外键关系的(Part)的实例。我不需要第二张桌子的模型

我只需要ProducedPart的只读版本

我总是可以在这上面实现一个Facade/Repository,但我希望在NH请求“ProducedPart”时设置一个映射,将“t_Part”与“PartProduction”结合起来

这是使用NH的错误方式吗

编辑

因此,SQL看起来像

SELECT p.* 
FROM t_Part p 
INNER JOIN t_PartProduction pp ON pp.PartID = p.PartID 
WHERE pp.ProductionYear = '2009'

不,这是完全可能的。在NHibernate文档中查找继承的“每个子类的表”模型。它实际上将实现这一点作为一个左连接,因此当您加载一个零件时,它将根据是否存在另一行创建您的零件或ProducedPart类的实例。您可以在上找到文档

不过,我不确定您是否可以将ProducedPart设置为只读

我从这里假设:

WHERE pp.ProductionYear = '2009'

您只希望在生产年为2009的子类中,即如果在TY PART生产中有一个不同年份的记录时,您希望将该部分视为普通的部分对象,而不是产品部分,然后您可以考虑在数据库中创建一个视图定义,该视图是TyPaTeaFug的已过滤版本,然后使您的子类连接到此视图而不是基表。

不,这是完全可能的。在NHibernate文档中查找继承的“每个子类的表”模型。它实际上将实现这一点作为一个左连接,因此当您加载一个零件时,它将根据是否存在另一行创建您的零件或ProducedPart类的实例。您可以在上找到文档

不过,我不确定您是否可以将ProducedPart设置为只读

我从这里假设:

WHERE pp.ProductionYear = '2009'

您只希望在生产年为2009的子类中,即如果在TY PART生产中有一个不同年份的记录时,您希望将该部分视为普通的部分对象,而不是产品部分,然后您可以考虑在数据库中创建一个视图定义,该视图是TyPaTeaFug的已过滤版本,然后使您的子类连接到此视图而不是基表。

我相信您正在寻找的是一个连接的子类。在FNH中,它将类似于:

public class PartMap : ClassMap<Part>
{
    public PartMap()
    {
        Id(x => x.Id)

        JoinedSubClass<ProducedPart>("PartID", sub => { 
            sub.Map(x => x.Name); 
            sub.Map(x => x.ProductionYear); 
        });
    }
}
公共类PartMap:ClassMap
{
公共零件图()
{
Id(x=>x.Id)
JoinedSubClass(“PartID”,sub=>{
sub.Map(x=>x.Name);
sub.Map(x=>x.ProductionYear);
});
}
}
为了让NHibernate缓存结果,您需要映射子类(如果您没有映射它,您将无法让NH首先加载它)


从中引入一些上下文,它将不会显式地是只读的。在我看来,对于NHibernate来说,将事物设置为只读并不是一件合适的事情。这可以更好地由数据库和连接控制(即,创建到数据库的连接,该数据库仅对正在访问的表/视图具有SELECT权限)。关于NHibernate中的只读会话,请参阅前面的SO问题,以了解我对该问题的更多想法。

我相信您正在寻找的是一个连接的子类。在FNH中,它将类似于:

public class PartMap : ClassMap<Part>
{
    public PartMap()
    {
        Id(x => x.Id)

        JoinedSubClass<ProducedPart>("PartID", sub => { 
            sub.Map(x => x.Name); 
            sub.Map(x => x.ProductionYear); 
        });
    }
}
公共类PartMap:ClassMap
{
公共零件图()
{
Id(x=>x.Id)
JoinedSubClass(“PartID”,sub=>{
sub.Map(x=>x.Name);
sub.Map(x=>x.ProductionYear);
});
}
}
为了让NHibernate缓存结果,您需要映射子类(如果您没有映射它,您将无法让NH首先加载它)


从中引入一些上下文,它将不会显式地是只读的。在我看来,对于NHibernate来说,将事物设置为只读并不是一件合适的事情。这可以更好地由数据库和连接控制(即,创建到数据库的连接,该数据库仅对正在访问的表/视图具有SELECT权限)。关于NHibernate中的只读会话,请参阅前面的SO问题,了解我对该问题的更多想法。

这里的关键是使用NHibernate映射的
where
mutable
类定义中的
元素

使用Fluent NHibernate,如下所示:

    public Part()
    {
        WithTable("t_Part");

        Id(i => i.Id).ColumnName("PartID");
        Map(m => m.Name).ColumnName("Part");

        SetAttribute("where", "PartID IN ( SELECT pp.PartID FROM t_PartProduction pp WHERE pp.ProductionYear = '2009' ) ");

        ReadOnly();
    }

这里的关键是对NHibernate映射使用
定义中的
where
可变
元素

使用Fluent NHibernate,如下所示:

    public Part()
    {
        WithTable("t_Part");

        Id(i => i.Id).ColumnName("PartID");
        Map(m => m.Name).ColumnName("Part");

        SetAttribute("where", "PartID IN ( SELECT pp.PartID FROM t_PartProduction pp WHERE pp.ProductionYear = '2009' ) ");

        ReadOnly();
    }

FNH没有ReadOnly()方法使模型成为只读的吗?是的,正如您所发现的,它将可变属性设置为false。如果您的应用程序是唯一一个接触数据库的应用程序,或者您不需要将数据保持为只读,那么这可能很好。但是,只要您使用到数据库的完全特权连接,任何代码都可以使用该连接绕过NH的speed bump并执行它想要的任何CRUD语句。这就是我在另一个答案中的意思;通过API使用建议只读(甚至是良好的设计)是很好的,但如果需要,应该在适当的级别强制执行。ProducedPart作为只读实际上只是查看数据的一种构造。它实质上是创建一个SQL
视图,查看当前年份已生产的部件,这对于我的项目来说是一个非常有用的习惯用法。因为这个模型基本上是虚拟的,所以我想确定一下,并确保它是不变的。谢谢我想我知道你现在要做什么了;对不起,如果我在切线上下车。只是