2013-12-01 3 views
2

Я новичок в LINQ, но я уже знаю основное различие между IQueryable и IEnumerable (т.е. условия, применяемые к первому, скорее всего, будут выполняться удаленным движком, в мой случай - переведен на SQL).NHibernate + LINQ - эффективная работа со связанными наборами

Теперь все учебники NHibernate, которые я когда-либо видел, используют IList<T> для соответствующих коллекций. Я хотел бы знать, есть ли способ использовать IQueryable, поэтому фильтрация может быть эффективной.

К сожалению, если я пытаюсь использовать IQueryable<T> как тип недвижимости для соответствующей коллекции, вызывает ошибку:

Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericBag 1[....PersonalDocument]' to type 'System.Linq.IQueryable

Поэтому, чтобы сохранить фильтрацию связанных коллекции SQL-стороны, мне нужно запросить соответствующие тип, непосредственно предоставляющий дополнительное условие, которое «связывает» отношение. Это довольно неудобно, и я хотел бы избежать этого (так как условие отношения уже объявлена ​​...)

Чтобы уточнить немного:

У меня есть две модели, а именно:

public partial class Person 
{ 
    public virtual int Id { get; set; } 
    // .... 
    public virtual IEnumerable<PersonalDocument> Documents { get; set; } 
} 

public class PersonalDocument 
{ 
// ... 
    public virtual int Id { get; set; } 
    public virtual Person Owner { get; set; } 
    public virtual string Type { get; set; } 
} 

и отображение кода для Person:

HasMany<DomainModel.PersonalDocument>(x => x.Documents) 
      .KeyColumn("Owner_Id") 
      .Inverse() 
      .Cascade.Delete() 
      .AsBag(); 

и код запроса

personInstance.Documents.Where(d => d.Type == "xx").Count() 

переводится в неоптимальной SQL (без «типа» фильтра, применяемого к SQL, рассчитывать сделано на стороне клиента) related

в то время как этот:

s.Query<PersonalDocument>().Count(x => x.Owner == personInstance && x.Type == "xx"); 

переводит к хорошим SQL:

enter image description here

есть ли способ Wr ite DRY LINQ, как и первый, но в результате SQL получается оптимальным, как второй?

ответ

0

Использование IList/ISet/IDictionary!

Вы можете создать коллекцию для каждого типа документа в классе Person. В картографии вы можете сделать:

HasMany(x => x.Documents) 
      .KeyColumn("Owner_Id") 
      .Inverse() 
      .Cascade.Delete() 
      .Where("Type=xx") 
      .AsBag(); 

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

Также взгляните на стратегии наследования NHibernate. На самом деле я думаю, что это именно то, что вы хотите:

http://www.nhforge.org/doc/nh/en/#inheritance
http://ayende.com/blog/3941/nhibernate-mapping-inheritance http://lostechies.com/jimmybogard/2008/08/27/strategies-and-discriminators-in-nhibernate/

+0

Это не решает мою проблему, мне нужна динамическая фильтрация. Название «тип» вводит в заблуждение здесь, мое намерение состоит не в том, чтобы иметь разные коллекции для разных типов, мне просто нужен способ динамического запроса против соответствующей коллекции. Кроме того, каждый тип документа имеет точно такие же поля, поэтому он не имеет ничего общего с различными классами/наследованием. – migajek

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