NHibernate 3 Linq和IUserType

时间:2012-05-13 10:52:30

标签: linq nhibernate 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; }
}

请注意,在域模型中,“Template”属性的类型不是“string”。 Template类是这样的:

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映射“Template”属性。

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

好的,到目前为止一切顺利。但问题是,如何在Linq查询中使用Template属性? 例如:

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

我认为解决方案可能是编写一个实现IHqlGeneratorForProperty的类(比如TemplatePropertyHqlGenerator)。这是NHibernate 3提供的linq查询扩展点。但是如何编写这个TemplatePropertyHqlGenerator类?

先谢谢!

1 个答案:

答案 0 :(得分: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