【问题标题】:Fluent NHibernate, working with interfaces流利的 NHibernate,使用接口
【发布时间】:2010-10-14 21:29:31
【问题描述】:

我刚切换到 Fluent NHibernate,遇到了一个问题,没有找到任何相关信息。

情况是这样的:

public class Field : DomainObject, IField
{
    public Field()
    {  
    }

    public virtual string Name { get; set; }
    public virtual string ContactPerson { get; set; }
    public virtual bool Private { get; set; }
    public virtual IAddress Address { get; set; }  
}

IAddress 是一个由Address 类实现的接口

public class Address : DomainObject, IAddress
{
    public Address()
    {
    }

    public virtual string City { get; set; }
    public virtual string Country { get; set; }
    public virtual string PostalCode { get; set; }
    public virtual string StreetAddress { get; set; }
}

这是我的两个类的映射文件

地址

public class AddressMap : ClassMap<Address>
{   
    public AddressMap()
    {
        WithTable("Addresses");
        Id(x => x.Id, "Id").Access.AsCamelCaseField(Prefix.Underscore).GeneratedBy.Guid();
        Map(x => x.City, "City");
        Map(x => x.Country, "Country");
        Map(x => x.PostalCode, "PostalCode");
        Map(x => x.StreetAddress, "StreetAddress");
    }
}

字段

public class FieldMap : ClassMap<Field>
{
    public FieldMap()
    {
        WithTable("Fields");
        Id(x => x.Id, "Id").Access.AsCamelCaseField(Prefix.Underscore).GeneratedBy.Guid();
        Map(x => x.Name, "Name");
        Map(x => x.ContactPerson, "ContactPerson");
        Map(x => x.Private, "Private");
        References(x => x.Address, "AddressId").Cascade.Delete().Cascade.SaveUpdate();
    }
}

因此,当我尝试从数据库中检索字段对象时,我收到 NHibernate 错误,指出 IAddress 未映射。有什么方法可以指定 NHibernate 在映射中使用 Address 类?

如果需要更多信息,请告诉我。

非常感谢,

查尔斯

【问题讨论】:

  • 如何在数据库中对 IAddress 层次结构进行建模?每个层次结构的表(一个包含所有类型地址的表),还是每个具体类的表?您说您切换到 Fluent,因此发布示例 XML 映射可能有助于确定您要完成的工作。
  • 事实上,我使用 Fluent NHibernate 从 ADO.NET Entity Framework 切换到了 Nhibernate。在我的数据库中,有一个包含所有类型地址的表。顺便说一句,我决定删除那些接口,我意识到它没有用。但我认为这个问题仍然有效。谢谢,查尔斯

标签: c# nhibernate interface mapping fluent


【解决方案1】:

在您的 Field 对象上,您有一个 IAddress 类型的对象。这可以通过任意数量的不同实现来实现。根据您的要求,每个实现都会有自己的映射,这会给 NHibernate 带来许多困难(不可能?)。

一个简单的例子将有助于演示。假设您有两个 IAddress 实现 Address1 和 Address2。它们都保存在自己的表 tblAddress1 和 tblAddress2 中。当您尝试加载您的 Field 对象时,NHibernate 所知道的只是您有实现 IAddress 的东西,它不知道哪个实现被持久化。它如何知道使用哪个映射来检索任何给定字段的子对象?

我敢肯定还有更多的复杂情况,但这个例子说明了为什么你必须为你声明的对象的确切类型建立一个映射。

【讨论】:

    【解决方案2】:

    我发现使用接口而不是具体类作为属性是有正当理由的。

    例如,如果您的 Field 类与 Address 类位于一个单独的项目中,并且您没有从 Field 类的项目中依赖 Address 类的项目。

    还有其他处理这种情况的方法,但最简单的方法通常是尝试您正在做的事情并明确告诉 NHibernate 用于 IAddress 的具体类。

    您现在可以在 Fluent NHibernate 中执行此操作,如下所示:

    References(x => x.Address, "AddressId")
        .Class(typeof(Address);
    

    很遗憾,您无法使用 HasMany 或 HasManyToMany 执行此操作。由于 C# 中缺乏良好的协方差支持,我不确定这是否可能。

    【讨论】:

    • 更新:你可以使用References&lt;Address&gt;(x =&gt; x.Address).Column("AddressId");你可以通过添加泛型类型参数来对'HasMany'和'HasManyToMany'做同样的事情。
    • 非常感谢,这正是我正在寻找的...尝试将 .CollectionType() 链接到我的 HasMany() 上,但这似乎不起作用。
    • +1 用于更新。 HasMany&lt;FeatureInstance&gt;(s =&gt; s.Features).KeyColumn("SiteId"); 其中 s.Features 是 IFeatureInstance 的集合
    • 谢谢,真的帮助迷路的人找到了方向。
    • @cbp 感谢您的回复。有可能的。使用 ReferencesAny。看github.com/jagregory/fluent-nhibernate/wiki/Fluent-mapping#any。然后使用 AddMetaValue 注册每个实例化接口的类。
    【解决方案3】:

    如果您有兴趣将 ORM 完全与域层分离,并在整个数据层中引用接口而不是指定具体类,则可以实现 EmptyInterceptor 在两者之间进行映射。

    看我的回答here

    【讨论】:

      猜你喜欢
      • 2011-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多