Я использую NHibernate 3.x вместе с Fluent NHibernate, и до сих пор у меня не было проблем с построением запросов к базе данных.
Чтобы упростить мои объекты для целей этого поста, я включил подмножество моих объектов и структур отображения ниже:
IssueItem
Класс сущности POCO:
public class IssueItem : DomainEntity, IKeyed<Guid> {
public virtual Guid ID { get; set; }
public virtual string Subject { get; set; }
public virtual string Description { get; set; }
public virtual IList<IssueLocation> Locations { get; set; }
}
Location
Класс сущности POCO:
public class Location : DomainEntity, IKeyed<Guid> {
public virtual Guid ID { get; set; }
public virtual string City { get; set; }
public virtual string State { get; set; }
public virtual string Zip { get; set; }
public virtual string Organization { get; set; }
public virtual IssueItem Issue { get; set; }
}
IssueItem
Свободная карта NHibernate:
public class IssueItemMap : DomainEntityMapping<IssueItem> {
public IssueItemMap()
{
Table("IssueItem");
LazyLoad();
Map(x => x.ID).Column("ID");
Map(x => x.Subject).Column("Subject");
Map(x => x.Description).Column("Description");
HasMany(x => x.Locations).KeyColumn("IssueItemID").LazyLoad().ReadOnly().Inverse();
}
}
Location
Свободная карта NHibernate:
public class LocationMap : DomainEntityMapping<Location> {
public LocationMap()
{
Table("Location");
LazyLoad();
Map(x => x.ID).Column("ID");
Map(x => x.City).Column("City");
Map(x => x.State).Column("State");
Map(x => x.Zip).Column("Zip");
Map(x => x.Organization).Column("Organization");
References(x => x.IssueItem).ForeignKey("IssueItemID").LazyLoad().ReadOnly();
}
}
Теперь я использую шаблон Unit of Work и Service / Repository в своем приложении MVC. Поэтому у меня есть доменный слой моего проекта, который содержит мои основные сущности POCO, а также валидаторы и сервисы. На моем уровне данных у меня есть материалы, связанные с NHibernate, такие как репозитории, к которым мой уровень домена получает доступ из моих сервисов. Здесь и живут мои карты NHibernate.
Чтобы убедиться, что никакая логика, специфичная для NHibernate, не проникает в мой уровень домена (на случай, если в будущем я захочу использовать другой ORM), я выполняю свои операторы LINQ в своих службах на уровне своего домена для объектов IQueryable, возвращаемых из репозитории в моем слое данных. Поэтому, когда я пишу свои запросы, я использую System.Linq и System.Linq.Expressions вместо класса NHibernate.Linq.
Тем не менее, вот мой запрос LINQ, с которым у меня возникают проблемы в одном из моих классов обслуживания на уровне моего домена:
var issues = _issueRepo.All();
if (!string.IsNullOrWhiteSpace(searchWords)) {
issues = issues.Where(i => i.Subject.Contains(searchWords)
|| i.Description.Contains(searchWords)
|| i.Locations.Where(l => l.Organization.Contains(searchWords)
|| l.City.Contains(searchWords))
.Select(x => x.IssueItemID).Contains(i.ID)
);
}
Теперь IssueItems
запрашиваются просто отлично. Однако таблица «один ко многим» (местоположения) не запрашивается должным образом. Это то, что я имею в виду ...
Сгенерированный оператор T-SQL идеален, за исключением самого его конца. Пример:
select TOP(100) issueitem0_.ID as ID2_, issueitem0_.Subject as Subject2_, issueitem0_.Description as Description2_
from IssueItem issueitem0_
where issueitem0_.Subject like ('%test%') or issueitem0_.Description like ('%test%')
or exists (select location1_.IssueItemID from Location location1_ where
issueitem0_.ID=location1_.IssueItemID and (location1_.Organization like ('%test%')
or location1_.City like ('%test%')) and location1_.ID=issueitem0_.ID)
Видите этот последний бит? Он добавляет последний оператор "и" (и location1_.ID = issueitem0_.ID), который выбрасывает ключ во всей системе. Я настроил каждый параметр конфигурации, который мог придумать в своем отображении, и перепробовал много разных операторов LINQ, и я не могу избавиться от этой последней части. Я не знаю, почему это добавляет это.
Если я создаю тот же оператор LINQ в LINQPad, он правильно генерирует оператор T-SQL без последней части (и location1_.ID = issueitem0_.ID).
Есть идеи?
Спасибо!
Joel