Fluent nhibernate 如何在nhibernate中映射接口?

Fluent nhibernate 如何在nhibernate中映射接口?,fluent-nhibernate,Fluent Nhibernate,我正在使用两个类NiceCustomer和RoughCustomer,它们实现了接口iccustomer iccustomer有四个属性。它们是: 属性Id()为整数 Property Name()作为字符串 属性IsNiceCustomer()为布尔值 ReadOnly属性AddressFullText()作为字符串 我不知道如何将接口iccustomer映射到数据库 我在内部异常中得到一个类似这样的错误 关联引用未映射的类:ICCustomer 我正在使用Fluent和NHibernate。

我正在使用两个类
NiceCustomer
RoughCustomer
,它们实现了接口
iccustomer

iccustomer
有四个属性。它们是:

  • 属性Id()为整数
  • Property Name()作为字符串
  • 属性IsNiceCustomer()为布尔值
  • ReadOnly属性AddressFullText()作为字符串
  • 我不知道如何将接口
    iccustomer
    映射到数据库

    我在内部异常中得到一个类似这样的错误

    关联引用未映射的类:ICCustomer


    我正在使用Fluent和NHibernate。

    无法在NHibernate中映射接口。如果您的目标是能够使用公共类型进行查询以检索这两种类型的客户,那么您可以使用多态查询。只需让两个类实现接口并正常映射类即可。见本参考资料:


    (第11.6节)

    您如何查询?如果您使用的是HQL,则需要使用以下行的HBM文件导入接口的命名空间:

    <import class="name.space.ICustomer, Customers" />
    
    
    
    如果您使用的是条件,您应该能够查询ICustomer,它将返回这两种客户类型

    如果要通过HasMany、HasManyToMany或引用映射一个拥有客户的类,则需要使用泛型形式:

    References<NiceCustomer>(f=>f.Customer)
    
    References(f=>f.Customer)
    
    如果您想让它处理其中的任何一个问题,您需要使它们成为子类

    Subclassmap<NiceCustomer>
    
    子类映射
    
    在这种情况下,我认为您需要基类Customer,并将其用于外部类中的泛型类型参数:

    References<Customer>(f=>f.Customer)
    
    References(f=>f.Customer)
    
    无论如何,你不应该改变你的域模型来处理这个问题,它应该在外部类上仍然有一个ICCustomer


    我不确定1.0RTM是否有用于引用的通用形式,但快速扫描更改应该会显示更改,我认为这是一个两行添加。

    您可以通过在配置阶段插入一个空的Interceptor,直接映射到NHibernate中的接口。这个拦截器的工作是为映射文件中定义的接口提供实现

    public class ProxyInterceptor : EmptyInterceptor
    {
        public ProxyInterceptor(ITypeHandler typeHandler) {
            // TypeHandler is a custom class that defines all Interface/Poco relationships
            // Should be written to match your system
        }
    
        // Swaps Interfaces for Implementations
        public override object Instantiate(string clazz, EntityMode entityMode, object id)
        {
            var handler = TypeHandler.GetByInterface(clazz);
            if (handler == null || !handler.Interface.IsInterface) return base.Instantiate(clazz, entityMode, id);
            var poco = handler.Poco;
            if (poco == null) return base.Instantiate(clazz, entityMode, id);
    
            // Return Poco for Interface
            var instance = FormatterServices.GetUninitializedObject(poco);
            SessionFactory.GetClassMetadata(clazz).SetIdentifier(instance, id, entityMode);
    
            return instance;
        }
    
    }
    
    在此之后,所有关系和映射都可以定义为接口

    public Parent : IParent {
        public int ID { get; set; }
        public string Name { get; set; }
        public IChild Child { get; set; }
    }
    
    public Child : IChild {
        public int ID { get; set; }
        public string Name { get; set; }
    }
    
    public class ParentMap : ClassMap<IParent>
    {
        public ParentMap()
        {
            Id(x => x.ID).GeneratedBy.Identity().UnsavedValue(0);
            Map(x => x.Name)
        }
    }   
    
    ...
    
    公共父级:IParent{
    公共int ID{get;set;}
    公共字符串名称{get;set;}
    public-IChild子项{get;set;}
    }
    公众儿童:IChild{
    公共int ID{get;set;}
    公共字符串名称{get;set;}
    }
    公共类ParentMap:ClassMap
    {
    公共ParentMap()
    {
    Id(x=>x.Id).GeneratedBy.Identity().UnsavedValue(0);
    映射(x=>x.Name)
    }
    }   
    ...
    

    如果您想要实现ORM的真正解耦,将所有配置/映射放在一个单独的项目中,并且只引用接口,那么这种技术是非常好的。这样,您的域层就不会受到ORM的污染,如果需要,您可以在以后的阶段替换它。

    我认为您不需要映射任何这样的接口。。你能把你的地图文件寄出去吗?感谢马赫什的回复。但正如Kevin所说,我们无法在nhibernate中映射接口。我已将接口更改为基类。我也尝试过多态查询,但它不起作用。与未映射的接口客户仍有问题。因此,现在将其作为一个基类,工作正常。非常感谢Kevin。“将命名的持久类作为接口是完全可以接受的。然后,您将使用元素声明该接口的实现类。”这个答案中的from链接被破坏。请更新链接或在答案中添加更多详细信息。能否在配置中添加使用ProxyInterceptor的示例?我现在刚开始使用Fluent Nhibernate,对配置部分不太熟悉,不知道在哪里指定代理…我能够让它工作,但问题是域层仍然被特定于ORM的方法过度污染——主要是属性设置器。ORM需要能够在每个字段上设置一个值,而在域对象中,我不希望能够更改对象的Id字段(与许多其他只读属性相同)。