#c# #nhibernate
#c# #nhibernate
Вопрос:
Мне нужно объединить 3 таблицы с помощью NHibernate Queryover, но я не могу заставить его работать. Есть предложения?
Я использовал этот код http://www.d80.co.uk/post/2011/02/20/Linq-to-NHibernate-Tutorial.aspx
Код NHibernate
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-запрос
SELECT * FROM Make INNER JOIN Model ON Make.Id = Model.MakeId
INNER JOIN Car ON Make.Id = Car.MakeId AND Model.Id = Car.ModelId
Комментарии:
1. Обычный способ — определить сопоставления между объектами, а не пытаться приблизить операторы SQL JOIN на уровне объекта. ORM существует именно для сопоставления отношений с правильными операторами SQL. Что вы пытаетесь сделать и почему вы думаете, что вам нужно
JOIN
? Вы пытаетесь получить make на основе определенной модели?2. Я новичок в NHibernate и ранее использовал операторы SQL. Я хочу получить как имя, так и описание (например, и его в другой таблице), если я не использую join, как мне тогда поступить?
3. ORM не являются альтернативным способом написания инструкций SQL. Вы определяете сущности ( не таблицы) и сопоставления объектов с таблицами, затем позволяете ORM создавать соответствующие инструкции. Если вы определяете a
Car
соModel
свойством иModel
у него есть aMake
, ORM загрузит все объекты, и вы сможете писатьmyCar=session.Get<Car>(id)
, а затемmyCar.Model.Make.Name
илиmyCar.Name
без явной загрузки чего-либо.4. Хорошо, я думаю, я понимаю. Но я не уверен, как это сделать в моем коде. Я обновил свой приведенный выше код всем кодом. Есть ли у вас какие-либо подсказки?
Ответ №1:
Разве вы не должны использовать список:
IList<Make> makeQuery = session.QueryOver<Make>()
.Where(_ => _.Name == _.Name)
.List()
Ответ №2:
Это даст вам все машины одной марки. Если вы хотите, чтобы все машины, очевидно, опустили where. Это то же самое, что вам даст SQL.
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>();
Вопрос в том, что вы хотите сделать?
Если вы хотите получить экземпляр объекта Make со всеми его моделями и автомобилями, то, очевидно, вам нужно добавить список автомобилей в класс модели (и подумать об использовании быстрой выборки). Я бы не рекомендовал это. Похоже, автор классов сущностей, то есть модели домена, хотел отделить домен make / model от домена физических машин. Мне это кажется хорошим. Если вам нужны все автомобили марки / модели, вы должны вернуть список автомобилей, и запрос NH вернет столько экземпляров объекта make / model, сколько строк make / model в результирующем наборе.
Невозможно вернуть make со всеми его автомобилями, пока класс модели не содержит список автомобилей 🙂
Если вы хотите вернуть пользовательский объект, вы можете использовать это для создания некоторого пользовательского преобразования, но я бы предпочел переосмыслить, что я хочу сделать, чем делать это.
Вы могли бы изучить проекции, они также полезны и имеют преобразования, но, я думаю, их не следует использовать для обхода отношений, не определенных в сущностях, например, model -> cars .
Комментарии:
1. Я хочу протестировать, как я получаю значения из всех «таблиц», чтобы изучить NHibernate
2. Этот запрос без предложения where вернет все автомобили с марками и моделями, используя вашу модель объекта (классы car, make и model). Это единственный возможный запрос, учитывая вашу модель сущности, который приведет к тому же sql, который вы указали.