tags:

views:

114

answers:

4

I have mapping:

<class name="User" table="Users" lazy="false">
  <id name="id" type="Int32" column="id">
    <generator class="identity" />
  </id>
  <property name="name" column="name" type="String"/>
  <map name="Urls" table="UserUrl" lazy="true" inverse="true" cascade="all">
     <key column="user_id"></key>
     <index column="url_type_id" type="Int32"/>
     <one-to-many class="UserUrl"/>
   </map>
</class>

<class name="UserUrl" table="UserUrl" lazy="false">
  <id name="id" type="Int32" column="id">
    <generator class="identity"/>
  </id>
  <property name="user_id" column="user_id" type="Int32" not-null="true"/>
  <property name="UrlType" column="url_type_id" type="Int32" not-null="true"/>
  <property name="Url" column="url" type="String" not-null="true"/>
</class>

Also I get

class User
{
  IDictionary<int,UserUrl> Urls;
 ....
}

User currentUser = FindById(2);
currentUser.Urls.Remove(5);

So I remove one item from assosiation collection of Url. Then I call SaveOrUpdateCopy(...), But url from table UserUrl doesn't delete and there is no error.

Does anybody know how to delete child item from collection and from DB?

+1  A: 

Set inverse to false for <map> element.

maciejkow
I try it, but I get error "Cannot insert the value NULL into column 'user_id', table 'dbo.UserUrl'; column does not allow nulls. UPDATE fails.The statement has been terminated."
A: 

Try this:

<map name="Urls" lazy="true" cascade="all-delete-orphans">
  • You don't need table, because the table is defined in the class UserUrl mapping
  • You should not make it inverse, if it is not
  • You should cascade it all-delete-orphan to tell NH to remove items that are removed from the collection.


Not related to your questions, why do you have this in the url?

<property name="user_id" column="user_id" type="Int32" not-null="true"/>

You are mapping the foreign key there! I would never ever dare to do this.


Actually, I'm not sure if you should not actually map it like this:

<map name="Urls" table="UserUrl" lazy="true" cascade="all-delete-orphans">
   <key column="user_id"/>
   <index column="url_type_id" type="Int32"/>
   <composite-element>
     <property name="UrlType" column="url_type_id" type="Int32" not-null="true"/>
     <property name="Url" column="url" type="String" not-null="true"/>
   </composite-element>
 </map>

If the Url is not an independent entity, having an own Id, then you could map it as composite-element. The url is treated as a value type. There is no class UserUrl mapping anymore.

Edit:

  • See the NH Reference Chapter 7, it explains the components.
  • If you get not-null problems on references, just remove the not-null constraint on the foreign key. NH needs to insert some columns to get primary keys if you use generator class="identity", so it stores a null temporary.
Stefan Steinegger
Thank you very much for answer. I use :<property name="user_id" column="user_id" type="Int32" not-null="true"/> to insert new UserUrl. I try to delete it from mapping and class and get error "Cannot insert the value NULL into column 'user_id' table 'dbo.UserUrl'" so it is nessesary
A: 

I try search in google but there is no information about difference between <map><one-to-many > and <map><composite-element> so I use <map><one-to-many >.
<map name="Urls" table="UserUrl" lazy="true" cascade="all-delete-orphans"> <key column="user_id"/> <index column="url_type_id" type="Int32"/> <composite-element> <property name="UrlType" column="url_type_id" type="Int32" not-null="true"/> <property name="Url" column="url" type="String" not-null="true"/> </composite-element> </map>


If the Url is not an independent entity, having an own Id, then you could map it
as composite-element. The url is treated as a value type.
There is no class UserUrl mapping anymore. I use UserUrl class in other code

You didn't understand components. See my answer, I added a Link. Btw, don't answer to your question if you are actually commenting to an answer. You could be down-voted.
Stefan Steinegger
Forgot to tell you this secret: you can select several lines together and make the appearing as source code (this just adds 4 spaces before each line). It also breaks on each line and has some pretty syntax highlighting. Don't use <pre>, <br>, <hl> aso. Just select text and use the buttons on top of the editor.
Stefan Steinegger
A: 

-Btw, don't answer to your question if you are actually commenting to an answer. You could be down-voted

-The problem is that I have no stackoverflow account, so only one way to login to site on the same name is to enter name and email under my post. I try to register account on that site with the same name and email, but when I log in it treats me as new user (not as I login fist time).
So I have no choice.

Also I find out that working code is

<map name="Urls" lazy="true" cascade="all-delete-orphans" inverse="true">

without inverse="true" it doesn't work.