NHibernate与Count一对多

时间:2022-10-04 10:49:49

I have entities Post and Tag, where there is a many-to-many relationship between the two (e.g. each post can have one or more tags, and each tag can be associated with any number of posts).

我有实体Post和Tag,其中两者之间存在多对多关系(例如,每个帖子可以有一个或多个标签,每个标签可以与任意数量的帖子相关联)。

What I would like to achieve is to have the Tag entity to have a field providing the number of posts which are associated with that tag. However, I don't know how to go about getting this without getting the entire collection of Posts (which I'd like to avoid).

我想要实现的是让Tag实体有一个字段,提供与该标签相关的帖子数量。但是,我不知道如何在没有获得整个帖子集合的情况下获得这个(我想避免)。

I am using Fluent NHibernate and my entities and mappings look like this currently:

我正在使用Fluent NHibernate,我的实体和映射目前看起来像这样:

Entities/Post.cs

public class Post : PersistentBase
{
    public virtual string Title { get; set; }
    /* snip */

    private IList<Tag> tags = new List<Tag>();
    public virtual IEnumerable<Tag> Tags {
        get { return tags; }
    }

    public virtual void AddTag(Tag tag) {
        this.tags.Add(tag);
    }
}

Mappings/PostMap.cs

public class PostMap : ClassMap<Post>
{
    public PostMap()
    {
        Id(x => x.Id).GeneratedBy.HiLo("99");
        Map(x => x.Title);
        /* snip */
        HasManyToMany(x => x.Tags);
    }
}

Entities/Tag.cs

public class Tag : PersistentBase
{
    public virtual string Name { get; set; }

    public static Tag Create(string name) {
        return new Tag { Name = name };
    }
}

Mappings/TagMap.cs

public class TagMap : ClassMap<Tag>
{
    public TagMap ()
    {
        Id(x => x.Id).GeneratedBy.HiLo("99");
        Map(x => x.Name).Unique();
    }
}

Ideally what I'd like to achieve is to be able to add into Entities/Tag.cs, something like the following:

理想情况下,我想要实现的是能够添加到Entities / Tag.cs​​,如下所示:

public virtual int PostCount { get; set; }

And then have that pre-filled with the number of posts using that tag.

然后预先填充使用该标签的帖子数量。

How might I go about doing this? (is it indeed possible?)

我该怎么做呢? (这确实可能吗?)

1 个解决方案

#1


3  

What you need is to define a formula in your Tag mapping.

您需要的是在标记映射中定义公式。

Here is how the Tag entity mapping should look like in XML (I am sure you can translate that to the Fluent NHibernate way):

以下是Tag实体映射在XML中的外观(我相信您可以将其转换为Fluent NHibernate方式):

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" ...>
    <class name="Tag" table="Tag">
        <id name="Id" type="Int32" column="TagID">
            <generator class="hilo" />
        </id>

        ...

        <property name="Name" column="Name" type="String" not-null="true" />
        <property name="PostCount" formula="(select count(*) from PostTag pt where pt.TagID = TagID)" type="Int32" insert="false" update="false" />

        ...
    </class>    
</hibernate-mapping>

This is assuming that your association table between Post and Tag in your Database is called PostTag. Please change the name accordingly to suit your needs.

这假设您的数据库中Post和Tag之间的关联表称为PostTag。请相应更改名称以满足您的需求。

Formulas work on the database level so are written in SQL and not HQL therefore the column names are used instead of the property names as you will notice in the XML above.

公式在数据库级别上工作,因此使用SQL而不是HQL编写,因此使用列名而不是属性名称,您将在上面的XML中注意到。

Then as you described you will need in the Tag.cs to add aproperty like this:

然后如您所述,您需要在Tag.cs​​中添加如下所示的aproperty:

public virtual int PostCount { get; protected set; }

#1


3  

What you need is to define a formula in your Tag mapping.

您需要的是在标记映射中定义公式。

Here is how the Tag entity mapping should look like in XML (I am sure you can translate that to the Fluent NHibernate way):

以下是Tag实体映射在XML中的外观(我相信您可以将其转换为Fluent NHibernate方式):

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" ...>
    <class name="Tag" table="Tag">
        <id name="Id" type="Int32" column="TagID">
            <generator class="hilo" />
        </id>

        ...

        <property name="Name" column="Name" type="String" not-null="true" />
        <property name="PostCount" formula="(select count(*) from PostTag pt where pt.TagID = TagID)" type="Int32" insert="false" update="false" />

        ...
    </class>    
</hibernate-mapping>

This is assuming that your association table between Post and Tag in your Database is called PostTag. Please change the name accordingly to suit your needs.

这假设您的数据库中Post和Tag之间的关联表称为PostTag。请相应更改名称以满足您的需求。

Formulas work on the database level so are written in SQL and not HQL therefore the column names are used instead of the property names as you will notice in the XML above.

公式在数据库级别上工作,因此使用SQL而不是HQL编写,因此使用列名而不是属性名称,您将在上面的XML中注意到。

Then as you described you will need in the Tag.cs to add aproperty like this:

然后如您所述,您需要在Tag.cs​​中添加如下所示的aproperty:

public virtual int PostCount { get; protected set; }