2013-09-11 6 views
2

Любая помощь приветствуется. Даже если вы можете сказать (исходя из вашего опыта), что использование ORM для такой огромной иерархии является безумным :).NHibernate: только объекты базового класса

Backgroud Мой модельный слой имеет довольно огромную иерархию классов, то есть около 200 классов. Хорошая/плохая вещь с иерархией заключается в том, что все они имеют один и тот же базовый класс. Максимальное расстояние между базовыми и листовыми классами равно 7, а классы максимального числа на любом уровне иерархии - 80. Я использую nHibernate для сохранения/загрузки данных из постоянного хранилища.

Задача Запросы, созданные nHibernate, довольно эффективны. например, если я хочу выбрать идентификаторы объектов на основе некоторого фильтра для свойства в базовом классе, 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 присоединится автомобили , автомобиль и велосипедный стол. В то время как все, что мне сейчас нужно только данные, хранящиеся в таблице Vehicle

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

Кто-нибудь знает, как я могу заставить NHibernate просто загрузить данные, в настоящее время необходимы, т.е. если он может возвращать только транспортное средство объекты вместо автомобиля/велосипеда ? С помощью всего лишь нескольких таблиц в вашей схеме вы можете игнорировать эти запросы по nHibernate, но это действительно больно, когда у вас 200 таблиц :(

PS В случае ошибки в модели, пожалуйста, игнорируйте это. реальная модель. Фактическая модель, как было сказано ранее, намного больше. Эта модель служит для иллюстрации проблемы.

+0

Вы можете попробовать установить Polymorphism.Explicit(); в сопоставлениях вашего базового класса (согласно http://stackoverflow.com/a/2094321/1236044 и http://stackoverflow.com/q/3396702/1236044) – jbl

+0

Как вы можете видеть разделы отображений в вопросе, Я уже пробовал это. Но, похоже, это не работает. – WPFAbsoluteNewBie

+0

не обратил внимания на это ;-) Как указано в комментариях о свободном ответе-NH, он, похоже, не работает со всеми стратегиями наследования. – jbl

ответ

2

NHibernate должен присоединиться к таблицам, чтобы решить, какой тип будет возвращен, иначе полиморфизм будет нарушен. сложнее обрабатывать случаи egde, такие как абстрактный базовый класс и т. д.

Проект только для вас, и вам хорошо идти

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

Если вам нужна Absolutly нужны только базовый класс, то на карте оно разделите для этого случая использования

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>(); 
+0

Спасибо, работает как ветер. –

Смежные вопросы