c# - NHibernate:仅加载基类对象

标签 c# database nhibernate fluent-nhibernate

欢迎任何形式的帮助。即使您可以说(根据您的经验)对于如此庞大的层次结构使用 ORM 是疯狂的:)。

背景 我的模型层有一个相当庞大的类层次结构,即大约有 200 个类。层次结构的好处/坏处是它们都具有相同的基类。基类和叶类之间的最大距离为 7,层次结构中任何级别的最大类数为 80。 我正在使用 nHibernate 从持久存储中保存/加载数据。

问题 nHibernate 生成的查询非常高效。例如,如果我想根据基类中某个属性的某些过滤器来选择对象的 id,NHibernate 将尝试连接层次结构/联合中的所有表,具体取决于我选择哪种映射策略,即每个子类一个表或每个类一个表层次结构。

据我了解,nHibernate 在扫描所有相关表之前不会识别哪种类型的对象。但是如果我现在只对基类数据感兴趣怎么办?如何强制 nHibernate 仅加载基类对象。

为了说明我的问题,这是一个简化版本

public class Vehicle
{
    public virtual Guid Identifier { get; set; }
    public virtual int WheelsCount { get; set; }
    public virtual Make Make { get; set; }
    public virtual Model Model { get; set; }
}

public class Bike : Vehicle
{
    public Bike()
    {
        WheelsCount = 2;
    }

    public virtual bool IsDirtBike { get; set; }
}

public class Car : Vehicle
{
    public Car()
    {
        WheelsCount = 4;
    }

    public virtual bool IsFourWheelDrive { get; set; }

    public virtual string Title { get; set; }
    public virtual string Description { get; set; }
}

public class Make
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Model> Models { get; set; }
}

public class Model
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual Make Make { get; set; }
}

映射关系如下

public class VehicleMap : ClassMap<Vehicle>
{
    public VehicleMap()
    {
        Id(x => x.Identifier).GeneratedBy.Guid();
        Map(x => x.WheelsCount);

        References(x => x.Make).Column("MakeId");
        References(x => x.Model).Column("ModelId");

        Table("Vehicle");
        Polymorphism.Explicit();
        UseUnionSubclassForInheritanceMapping();
    }
}

public class BikeMap : SubclassMap<Bike>
{
    public BikeMap()
    {
        Map(x => x.IsDirtBike);
        Table("Bike");
        // Abstract();
    }
}

public class CarMap : SubclassMap<Car>
{
    public CarMap()
    {
        Map(x => x.Title);
        Map(x => x.Description);
        Map(x => x.IsFourWheelDrive);
        Table("Car");
       // Abstract();
    }
}

public class MakeMap : ClassMap<Make>
{
    public MakeMap()
    {
        Id(x => x.Id);
        Map(x => x.Name);
        HasMany(x => x.Models)
            .KeyColumn("MakeId");
        Table("Make");
    }
}

public class ModelMap : ClassMap<Model>
{
   public ModelMap()
   {
       Id(x => x.Id);
       Map(x => x.Name);
       References(x => x.Make)
           .Column("MakeId");
       Table("Model");
   }
}

现在,如果运行以下查询来加载四轮车辆,NHibernate 将连接车辆、汽车和自行车表。而我现在需要的只是车辆表中存储的数据

List<Vehicle> vehicles = session.Query < Vehicle > ().Where(v => v.WheelsCount > 2).ToList();

有谁知道如何强制 nHibernate 仅加载当前需要的数据,即它是否只能返回车辆对象而不是汽车/自行车?只要架构中只有几个表,您就可以忽略 nHibernate 的这些查询,但当您有 200 个表时,这真的很痛苦:(。

附注如果型号有问题,请忽略。这不是真实的模型。如前所述,实际模型要大得多。这个模型就是用来说明问题的。

最佳答案

NHibernate 必须连接表来决定返回哪种类型。否则多态性就会被破坏。而且处理像抽象基类之类的egde情况也会更加困难。

仅投影您需要的属性,然后就可以开始

var vehicledatas = session.Query<Vehicle>()
    .Where(v => v.WheelsCount > 2)
    .Select(v => new { v.Id, v.WheelCount, v.Price })
    .ToList();

如果您绝对只需要基类,则针对此用例单独映射它

public class AlternateVehicleMap : VehicleMap
{
    public AlternateVehicleMap()
    {
        EntityName("IAbsolutlyWantOnlyTheBaseClass");
        Readonly();   // to make sure noone messes up
    }
}

List<Vehicle> vehicles = session.CreateCriteria<Vehicle>("IAbsolutlyWantOnlyTheBaseClass").Add(Expression.Gt("WheelsCount", 2).List<Vehicle>();

关于c# - NHibernate:仅加载基类对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18740666/

相关文章:

nhibernate - 将复合键映射到两个外键

c# - 为什么 NHibernate 不从数据库中删除?

c# - 在单击事件处理程序中从 ToolStripMenuItem 和 Button 获取 Tag 属性

c# - C# 中 OAuth 随机数的线程安全随机数/字符串生成器

java - 平面 xml 数据集的 dbUnit xml 文件格式

sql - 如何根据不同的条件从同一个表的不同行中检索数据

mysql - Siteground 托管到 AWS RDS 连接花费太多时间

c# - 如何从用属性修饰的 C# 类生成 .proto 文件?

c# - 为什么 C# 自动属性不支持像 VB 2010 这样的默认值?

c# - 什么是限制请求数?为什么是 `Timeout while getting a connection from pool` ?