【问题标题】:nHibernate (w/ Castle ActiveRecord) with C# interfaces (esp for DTO's)nHibernate (w/ Castle ActiveRecord) 与 C# 接口 (esp for DTO's)
【发布时间】:2009-03-12 04:34:58
【问题描述】:

任何将 nHibernate 与从公共接口实现的域对象和 DTO 对象一起使用?我正在尝试将我所有的 nHibernate 属性分离到 Domain 对象中,让我的 DTO 和界面保持干净。

当 nHibernate 尝试将接口与具体类关联时,会出现问题。

NHibernate.MappingException:关联引用未映射的类:IContact

我理解为什么它抱怨使用非休眠界面,但我正在努力寻找一种围绕它进行重组的方法。我的代码的骨架复制如下所示,对于如何更好地构建我的代码有什么想法吗?

public interface ICompany
{
    IList<IContact> Contacts { get; set; }
}

public class CompanyDTO : ICompany
{
    private IList<IContact> contacts;
    public IList<IContact> Contacts { get { return this.contacts; } set { this.contacts = value; } }

}

[ActiveRecord]
public class Company : ActiveRecordBase<Company>, ICompany
{
    private IList<IContact> contacts;
    [HasMany(Inverse=true, Table="Contact", ColumnKey="CompanyId")] 
    [ScriptIgnore]
    public IList<IContact> Contacts { get { return this.contacts; } set { this.contacts = value; } }
}

编辑:

我想要一个通用接口,这样我就可以确保它们保持相同的字段(即依靠编译器来保持它们的一致性)。它还允许我在应用程序的视图部分中使用 DTO,但将它们转换为域对象以进行业务和数据访问。 此外,alex 的解决方案不起作用,因为 ICompany 的联系人是 IList 类型,而不是 IList。我想将其保留为 IContact,因此我的 DTO 对象不知道 Contact Domain 对象。

【问题讨论】:

    标签: c# asp.net nhibernate castle-activerecord dto


    【解决方案1】:

    在您的具体情况下,您应该将 Type = typeof(Contact) 添加到映射属性,如下所示:

    [HasMany(Inverse=true, Table="Contact", ColumnKey="CompanyId", Type=typeof(Contact))]
    

    【讨论】:

    • Hej,你也知道如何用 Fluent 做到这一点吗? :)
    【解决方案2】:

    在您的域中,您不能使用 IContract 来引用您的域实体,而是使用 Concrete 类。如果您想更正您的版本,只需使用以下命令:

    [ActiveRecord]
    public class Company : ActiveRecordBase<Company>
    {
        private IList<Contact> contacts;
        [HasMany(Inverse=true, Table="Contact", ColumnKey="CompanyId")] 
        [ScriptIgnore]
        public IList<Contact> Contacts { get { return this.contacts; } set { this.contacts = value; } }
    }
    

    我看不出连接您的域和 DTO 的意义。它们是耦合的,并且它们可以具有不同的信息。例如,您可以将一些信息非常封装到您的域中,并且只传达很少的其他信息。 DTO 用于传输您要与上层共享的数据。

    您可以使用 Base 类来定义您的实体和您的 ValueObject。简而言之 Entity : DomainEntity 是 ID 能够意味着它们可以被持久化。 ValueObject = DTO 无法持久化(无法识别)

    看看Sharp-Arch的核心设计:

    • /BaseObject.cs:提供基本的对象比较服务。
    • /Entity.cs:为对象提供域 签名和可键入的 ID 属性。这也有验证 支持 NHibernate 验证器。从实体扩展的对象 必须至少有一个 [DomainSignature] 属性;它会抛出一个 如果违反这一点,则按合同设计例外。界面 IEntityWithTypedID 允许您自己滚动。
    • /ValueObject.cs:这是一个值对象,其中所有 与另一个值对象比较时使用属性。对象 从 ValueObject 扩展的可能没有任何 [DomainSignature] 特性;如果是这样,它将抛出一个按合同设计的异常 违反。

    【讨论】:

    • 我想要一个通用接口,这样我就可以确保它们保持相同的字段(即依靠编译器来保持它们的一致性)。它还允许我在应用程序的视图部分中使用 DTO,但将它们转换为域对象以进行业务和数据访问
    • 另外,您的解决方案不起作用,因为 ICompany 的联系人属于 IList 类型,而不是 IList。我想将其保留为 IContact,因此我的 DTO 对象不知道 Contact Domain 对象。
    • 抱歉做了更改删除了接口实现
    • 您不能将 ContactDto 直接转换为 Contact 您仍然需要使用转换。您可以将 ContactDto 转换为 IContact 但不能转换为 Contact
    【解决方案3】:

    如果我有 [HasMany] 属性,我该怎么办?它实际上没有属性名称 'Type',但 [Property] 和 [BelongsTo] 有。

    更新

    答案是使用CollectionType = typeof(YourType)

    更新 2

    不,它不起作用,此属性是为集合类型设置的,即列表等。 尝试设置 [HasMany(typeof(meType), ...)] 但仍然无效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多