nHibernate(带有 Castle ActiveRecord),带有 C# 接口(特别是 DTO)

发布于 2024-07-15 02:42:25 字数 1150 浏览 8 评论 0原文

任何将 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 对象。

Any using nHibernate with a Domain object & DTO object implemented from a common interface? I'm trying to separate all of my nHibernate attributes into the Domain object, leaving my DTO's and interface clean.

The problem comes with nHibernate throwing errors when it tries to associate the interfaces with the concrete classes.

NHibernate.MappingException: Association references unmapped class: IContact

I understand why its complaining about the use of the non-hibernated interface, but I'm struggling to visual a way to restructure around it. A skeleton reproduction of my code is set out as below, any ideas for how to structure my code better?

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

Edit:

I want to have a common interface so that I can ensure they are keeping the same fields (ie. leaning on the compiler to keep them consistent). It also allows me to use the DTO's in the view part of my application, but casts them to domain objects for business and data access.
Also, alex's solution does not work because ICompany's Contacts is of type IList, not IList. I would like to keep it as IContact so my DTO object has no knowledge of the Contact Domain object.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蓝眼泪 2024-07-22 02:42:25

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

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

In your concrete case you should just add Type = typeof(Contact) to the mapping attribute, like so:

[HasMany(Inverse=true, Table="Contact", ColumnKey="CompanyId", Type=typeof(Contact))]
瘫痪情歌 2024-07-22 02:42:25

那么在您的域中,您不能使用 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 用于传输您想要与上层共享的数据。

您可以使用基类来定义您的实体和 ValueObject。 简而言之,实体:DomainEntity 具有 ID 能力,意味着它们可以被持久化。 ValueObject = DTO无法持久化(无法ID)

看一下Sharp-Arch的核心设计:

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

Well in your domain you can't use the IContract to reference to your domain entity use Concrete class instead. If you want to correct your version use simply this:

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

I don't see the point to interface your domain and your DTOs. They are coupled, and they can have not the same informations. For example you could keep some information very weel encapsulated into your Domain and only communicate few other informations. DTO are made to transfert the data you want to share with up-layers.

You can have Base class to define your entity and your ValueObject. In brief Entity : DomainEntity are ID able means they can be persisted. ValueObject = DTO cannot be persisted (not ID able)

Look at the core design of Sharp-Arch:

  • /BaseObject.cs: Provides basic object comparative services.
  • /Entity.cs: Provides an object with a domain
    signature and a typeable ID property. This also has the validation
    support of NHibernate Validator. Objects which extend from Entity
    MUST have at least one [DomainSignature] property; it'll throw a
    Design-By-Contract exception if this is violated. The interface
    IEntityWithTypedID allows you to roll your own.
  • /ValueObject.cs: This is a value object wherein all of its
    properties are used when compared to another value object. Objects
    which extend from ValueObject may not have any [DomainSignature]
    properties; it'll throw a Design-By-Contract exception if this is
    violated.
以可爱出名 2024-07-22 02:42:25

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

UPDATE

答案是使用 CollectionType = typeof(YourType)

UPDATE 2

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

And what shall i do if i have [HasMany] attribute? It actually hasn't property name 'Type', but [Property] and [BelongsTo] ones have.

UPDATE

The answer is to use CollectionType = typeof(YourType)

UPDATE 2

No, It doesn't working, this property is set for collection type i.e. List etc.
Trying to set [HasMany(typeof(meType), ...)] but still not works.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文