1

I want to map a M:N asociation betwen Products and Cart with asociation class ProductsOfCart betwen them. However data is not persister but I dont know why can you help me?

Here is a code from CartControler

Create();

Product productD = new ProductDao().GetById(product);

ProductsOfCart productsOfCart = new ProductsOfCart();

User user = new UserDao().GetByLogin(User.Identity.Name);

Cart cart = new CartDao().GetByUser(user);

cart.Price += productD.Price;
cart.PriceDph += productD.PriceDph;
cart.NumberOfItems++;

ProductsOfCartDao productsOfCartDao = new ProductsOfCartDao();

CartDao cartDao = new CartDao();

CartDao.Update(cart);

productsOfCart.IdCart = cart;

productsOfCart.IdCart = productD;

productsOfCartDao.Create(productsOfCart);

Cart, Product and ProductsOfCart

public class Cart :IEntity
{

    public virtual int Id { get; set; }

    public virtual double Price { get; set; }

    public virtual double PriceDph { get; set; }

    public virtual int NumberOfItems { get; set; }

    public virtual User IdUser { get; set; }

    public virtual IList<Product> Products { get; set; }  
}

public class Product : IEntity
{

    public virtual int Id { get; set; }

    public virtual string Name { get; set; }

    public virtual int Price { get; set; }

    public virtual string ProductState { get; set; }

    public virtual string Maker { get; set; }

    public virtual string Description { get; set; }

    public virtual int ProductWaranty { get; set; }

    public virtual ProductCategory Category { get; set; }

    public virtual string ImageName { get; set; }

    public virtual IList<Cart> Carts { get; set; }
}

public class ProductsOfCart : IEntity
{
    public virtual int Id { get; set; }

    public virtual Product IdProduct { get; set; }

    public virtual Cart IdCart { get; set; }

}

And here are XML files of Product, Cart and ProductsOfCart

<class name="Product" table="Products">
    <id name="Id" column="id_product">
      <generator class="native" />
    </id>
    <property name="Name" column="name" />
    <property name="Price" column="price" />
    <property name="ProductState" column="productState" />
    <property name="Maker" column="maker" />
    <property name="Description" column="description" />
    <property name="ProductWaranty" column="productWaranty" />
    <many-to-one name="Category" column="id_category" foreign-key="id_category" />
    <property name="ImageName" column="imageName" />
<bag name="Carts" lazy="true"
   inverse="true" batch-size="25" cascade="all-delete-orphan">
  <key column="id_product" />
  <one-to-many class="ProductsOfCart" />
</bag>

</class>

<class name="Cart" table="Carts">
    <id name="Id" column="id_cart">
      <generator class="native" />
    </id>
    <property name="Price" column="price" />
    <property name="PriceDph" column="priceDph" />
    <property name="NumberOfItems" column="numberOfItems" />
    <many-to-one name="IdUser" column="id_User" foreign-key="id_User" />
  <bag name="Products" lazy="true" 
   inverse="true" batch-size="25" cascade="all-delete-orphan">
  <key column="id_cart" />
  <one-to-many class="ProductsOfCart" />
</bag>
</class>

<class name="ProductsOfCart" table="ProductsOfCart">
    <id name="Id" column="id_ProductsOfCart">
      <generator class="native" />
    </id>
    <many-to-one name="IdProduct" column="id_product" foreign-key="id_product"/>
    <many-to-one name="IdCart" column="id_cart" foreign-key="id_cart" />
</class>

1 Answers1

0

If we want to create the pairing object as entity. We need mapping like this:

<class name="Product" table="Products">
    ... // as is    
    <bag name="Categories" lazy="true" 
       inverse="true" batch-size="25" cascade="all-delete-orphan">
      <key column="id_product" />
      <one-to-many class="ProductsOfCart" />
    </bag>

</class>

<class name="Cart" table="Carts">
    ... // as is    
    <bag name="Products" lazy="true" 
       inverse="true" batch-size="25" cascade="all-delete-orphan">
      <key column="id_cart" />
      <one-to-many class="ProductsOfCart" />
    </bag>
</class>


<class name="ProductsOfCart" table="ProductsOfCart">
    <many-to-one name="Product" column="id_product" />
    <many-to-one name="Cart" column="id_cart"  />
</class>

And our classes would look like:

public class Cart :IEntity
{
    ...
    public virtual ILIst<ProductCategory> Products { get; set; }   
}

public class Product : IEntity
{
    ...
    public virtual IList<ProductCategory> Categories { get; set; }
}

public class ProductCategory : IEntity
{
    ...
    public virtual Product Product{ get; set; }
    public virtual Category Category { get; set; }
}

This structure is what I would prefer. It is easy to create complex queries on top of it... Try to read more for example here many-to-many with extra columns nhibernate

But we also could hide the pairing table, and use mapping many-to-many, which would totally hide the pairing table and pairing C# object

<class name="Product" table="Products">
    ... // as is    
    <bag name="Categories" lazy="true" 
       table="ProductsOfCart" // many-to-many requires table defintion
       inverse="true" batch-size="25"
       cascade="none"> // cascade would not effect the pair, but Category
                       // usually not wanted
      <key column="id_product" />
      <many-to-many class="Category" column="id_product" />
    </bag>

</class>

<class name="Cart" table="Carts">
    ... // as is    
    <bag name="Products" lazy="true" table="ProductsOfCart"
       inverse="false"  // one side MIGHT NOT be inverse
       batch-size="25" 
       cascade="none"> // cascade would not effect the pair, but Product
                      // usually not wanted
      <key column="id_cart" />
      <many-to-many class="Product" column="id_product" />
    </bag>
</class>

And our classes would look like:

public class Cart :IEntity
{
    ...
    public virtual IList<Product> Products { get; set; }   
}

public class Product : IEntity
{
    ...
    public virtual IList<Category> Categories { get; set; }
}

Read about many to many also here NHibernate map one-to-many relationship with intermediate table

EXTEND

In case that you are provide with No persiter... exception be sure:

  • all hbm mapping files really do have suffix .hbm.xml (check any typo)
  • all hbm mapping files must be Embedded resources
  • the configurtion must contain (more here):

NH session factory config

    ...
    <mapping assembly="Project.DomainModel"/>  <!-- Here -->
</session-factory>

Also, the latest mapping in the question is correct - while C# stuff is not. To have this mapping of collection :

(Product.hbm.xml)

...
<bag name="Carts" lazy="true"
   inverse="true" batch-size="25" cascade="all-delete-orphan">
  <key column="id_product" />
  <one-to-many class="ProductsOfCart" />
</bag>

C# POCO must be:

public class Product : IEntity
{
    ...
    // instead of this
    // public virtual IList<Cart> Carts { get; set; }
    // we need this
    public virtual IList<ProductsOfCart> Carts { get; set; }
}

This should be enough information to make it running, I'd say

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • When you have there ProductCategory you mean Cart? However I tried it and stil data are not persister can I have mistake somewhere else? – MrLucker518 Jun 05 '15 at 19:04
  • Be sure, that 1) your mapping files have exactly this extension `...hbm.xml` 2) that these files do have property "Embedded resource" these could be the reasons why your mapping is not loaded and used... – Radim Köhler Jun 05 '15 at 19:21
  • I checked it twice but still not persisted. Do you think that I can sent it to you because I cant see the mistake but other eyes might see it. – MrLucker518 Jun 05 '15 at 19:32
  • Well, the best is to use SO. Could you update your question with the latest stuff you have? – Radim Köhler Jun 05 '15 at 19:34
  • Sorry, won't be near some time.. if you won't find help (but you really should google it, and use my snippets) we can continue later.. good luck – Radim Köhler Jun 05 '15 at 19:42
  • We are on a good way now I have this exception: Illegal attempt to associate a collection with two open sessions – MrLucker518 Jun 06 '15 at 13:11