简体   繁体   中英

Inner join 3 tables with NHibernate Queryover

I need to join 3 tables with NHibernate Queryover , but I cant get it to work. Any suggestions?

I used this code http://www.d80.co.uk/post/2011/02/20/Linq-to-NHibernate-Tutorial.aspx

NHibernate code

namespace SimpleNHibernateClient.ConsoleApplication
{
class Program
{
    static void Main(string[] args)
    {
        ReadALL();
        Console.ReadKey();
    }

    private static Make ReadALL()
    {
        using (var session = NHibernateHelper.OpenSession())
        {
            var makeQuery = session.QueryOver<Make>()
            .Where(_ => _.Name == _.Name)
            .List()

            foreach (var m in makeQuery)
            {
                Console.WriteLine("Name: " + m.Name);
                Console.WriteLine("Description: " + m.Description); //Dont Work
            }
            return null;
        }
    }

}

public class Car
{
    public virtual int Id { get; set; }
    public virtual string Title { get; set; }
    public virtual string Description { get; set; }
    public virtual Make Make { get; set; }
    public virtual Model Model { 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; }
}
 }


 namespace SimpleNHibernateClient.ConsoleApplication
 {
public class CarMap : ClassMap<Car>
{
    public CarMap()
    {
        Id(x => x.Id);
        Map(x => x.Title);
        Map(x => x.Description);
        References(x => x.Make).Column("MakeId");
        References(x => x.Model).Column("ModelId");
        Table("Car");
    }
}

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");
    }
}




namespace SimpleNHibernateClient.ConsoleApplication
{
    public class NHibernateHelper
    {
        private static ISessionFactory _sessionFactory;

        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                    InitializeSessionFactory();

                return _sessionFactory;
            }
        }

        private static void InitializeSessionFactory()
        {
            _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008
                              .ConnectionString(
                                  @"Server=localhost;Database=SimpleNHibernate;Trusted_Connection=True;")

                )
                .Mappings(m =>
                          m.FluentMappings
                              .AddFromAssemblyOf<Car>())
                .BuildSessionFactory();
        }

        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }
    }
}

}

SQL Query

SELECT * FROM Make INNER JOIN Model ON Make.Id = Model.MakeId 
INNER JOIN Car ON Make.Id = Car.MakeId AND Model.Id = Car.ModelId

Shouldn't you be using a list:

 IList<Make> makeQuery = session.QueryOver<Make>()
            .Where(_ => _.Name == _.Name)
            .List()

This will give you all the cars of one make. If you want all the cars omit the where obviously. This is the same as what the SQL would give you.

Car car = null; 
Make make = null;
Model model = null; 
List<Car> cars = 
    session
        .QueryOver<Car>(() => car)
        .JoinAlias(() => car.Make, () => make)
        .JoinAlias(() => car.Model, () => model)
        .Where(() => make.Name == makeName)
        .List<Car>();

The question is what you want to do?

If you want to get a Make object instance with all it's Models and Cars then obviously you need to add a List of cars to the Model class (and think about using eager fetching). I would not recommend this. It seems the author of the entity classes, ie the domain model, wanted to separate the make/model domain from the domain of physical cars. Which seems good to me. If you want all the cars of a make/model, you should return a list of cars, and the NH query will return only as many make/model object instances as the count of make/model rows in the resultset.

It is not possible to return a make with all its cars while the model class doesn't contain a list of cars :)

If you want to return a custom object, you can use this to create some custom transformation, but I would rather re-think what it is I want to do than do this.

You could look into projections , they are also useful, and have transformations, but, I think, should not be used to traverse relations not defined in the entities, eg model -> cars.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM