2009-11-21 2 views
0

У меня есть объекты Post и Tag, где между ними существует взаимосвязь «многие-ко-многим» (например, каждое сообщение может иметь один или несколько тегов, и каждый тег может быть связан с любым количество должностей).NHibernate Many-to-many with Count

То, что я хотел бы достичь, состоит в том, чтобы объект Tag имел поле, предоставляющее количество сообщений, связанных с этим тегом. Тем не менее, я не знаю, как это сделать, не получив всю коллекцию Post s (чего я бы хотел избежать).

Я использую 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); 
    } 
} 

отображения/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); 
    } 
} 

Сущности/Tag.cs ​​

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

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

Отображения/TagMap.cs

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

В идеале я хотел бы добиться того, чтобы иметь возможность добавлять в Entities/Tag.cs, что-то вроде следующего:

public virtual int PostCount { get; set; } 

И после этого у вас будет заполнено количество сообщений, использующих этот тег.

Как я могу это сделать? (действительно ли это возможно?)

+0

у не нужен класс tagmap –

ответ

3

Что вам нужно, это определить формулу в вашем сопоставлении тегов.

Вот как отображение объекта 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> 

Это при условии, что ваша таблица связи между Post и Tag в ваша база данных называется PostTag. Пожалуйста, измените название в соответствии с вашими потребностями.

Формулы работают на уровне базы данных, поэтому они написаны на языке SQL, а не в HQL, поэтому вместо имен свойств используются имена столбцов, как вы заметили в приведенном выше XML.

Тогда как вы описали вы будете нуждаться в Tag.cs ​​добавить aproperty так:

public virtual int PostCount { get; protected set; } 
+0

Как бы сделать, если формула устанавливается в классе отображения вместо xml-файл, и я не могу использовать таблицу ассоциаций (PostTag) в формуле, потому что имена таблиц выполняются соглашениями в другой сборке? –

+0

@Nicolas Я предполагаю, что вы используете FluentNHibenrate, но это не меняет того факта, что формулы являются сырым SQL, и это означает, что вам придется жестко кодировать имена таблиц, используемые в них. Если вам известно об используемом соглашении, просто поместите имя таблицы в формулу, поскольку соглашение сгенерирует ее.Я не знаю, как FluentNHibernate возвращает сгенерированные имена таблиц (из используемых условностей), чтобы вы могли использовать их внутри своей формулы. – tolism7