2012-05-13 3 views
0

У меня есть таблица:NHibernate 3 Linq и IUserType

Page (
    Id int, 
    Name nvarchar(50), 
    TemplateName varchar(50) 
    ... 
) 

и это отображается в модели предметной области:

public class Page { 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Template Template { get; set; } 
} 

Обратите внимание, что в модели предметной области, свойство «Шаблон» не относится к типу " строка». Шаблон класса выглядит так:

public class Template { 
    public string Name { get; set; } 
    // other properties... 
} 

«Шаблоны» загружаются из файловой системы. У меня есть класс TemplateManager:

public class TemplateManager { 
    public static Template LoadTemplate(string templateName) { 
     // check if there's a folder named <templateName> 
    } 
} 

можно использовать IUserType отобразить свойство «Шаблон».

public class PageMap : ClassMapping<Page> { 
    public PageMap() { 
     ... 
     Property(c => c.Template, m => { 
      m.Column("TemplateName"); 
      m.Type<TemplateUserType>(); 
     } 
    } 
} 

public class TemplateUserType : IUserType { 
    public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner) 
    { 
     var templateName = rs[names[0]].AsString(); 

     if (!String.IsNullOrEmpty(templateName)) 
     { 
      return TemplateManager.LoadTemplate(templateName); 
     } 

     return null; 
    } 
} 

Хорошо, пока все хорошо. Но проблема в том, как я могу использовать свойство Template в запросах Linq? Для exmaple:

var pages = session.Query<Page>().Where(it => it.Template.Name == "MyTemplate"); 

Я думаю, что решение может быть, чтобы написать класс (скажем, TemplatePropertyHqlGenerator) реализации IHqlGeneratorForProperty. Это точка расширения запроса linq, предоставленная NHibernate 3. Но как написать этот класс TemplatePropertyHqlGenerator?

Спасибо, продвинутый!

ответ

0

Интерфейс IUserType позволяет определить тип, который считается атомарным. То есть вы можете выполнить прямые сравнения между экземплярами типа, а NHibernate будет знать, как их перевести.

E.g. следующий запрос будет оценивать:

var template = new Template(); 
session.Query<Page>().Where(it => it.Template == template); 

Если вы хотите, чтобы определить тип, который имеет компонент значения, которые затем можно манипулировать, необходимо реализовать интерфейс ICompositeUserType. Этот интерфейс требует, чтобы вы определяли свойства типа как атомные элементы, предоставляя NHibernate информацию, необходимую ему для понимания конкретных свойств этого типа.

В результате, это немного сложнее, чем IUserType для реализации, но это должно облегчить то, чего вы хотите достичь.

Вот понятно пример реализации интерфейса для типа Money: http://geekswithblogs.net/opiesblog/archive/2006/08/05/87218.aspx

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