2009-09-07 9 views
0

Je travaille sur une application mvc en utilisant NHibernate comme ORM (cadre ncommon)Suppression d'un enregistrement des enfants non référencées avec NHibernate

je entités parent/enfant: Produit, fournisseur & ProductVendors et un à plusieurs entre eux avec Produit ayant une collection ProductVendors Product.ProductVendors.

Je suis actuellement en train de récupérer un objet Product et j'ai hâte de charger les enfants et de les envoyer à mon client mvc asp.net.

Un utilisateur modifiera alors la liste des fournisseurs et affichera le produit mis à jour. J'utilise un classeur de modèle personnalisé pour générer l'entité produit modifiée. Je suis capable de mettre à jour l'amende du produit et d'insérer de nouveaux ProductVendors.

Mon problème est que ProductVendors déréférencés ne sont pas supprimés en cascade lorsque vous spécifiez Product.ProductVendors.Clear() et que vous appelez _productRepository.Save (product).

Le problème semble être d'attacher l'instance détachée. Voici mes fichiers de mappage:

Produit

<?xml version="1.0" encoding="utf-8" ?> 

<id name="Id"> 
    <generator class="guid.comb" /> 
</id> 

<version name="LastModified" 
       unsaved-value="0" 
       column="LastModified" 
       /> 

<property name="Name" type="String" length="250" /> 

ProductVendors

<?xml version="1.0" encoding="utf-8" ?> 

<id name="Id"> 
    <generator class="guid.comb" /> 
</id> 

<version name="LastModified" 
       unsaved-value="0" 
       column="LastModified" 
       /> 

<property name="Price" /> 

<many-to-one 
    name="Product" 
    class="Product" 
    column="ProductId" 
    lazy="false" 
    not-null="true" 
    /> 

<many-to-one 
name="Vendor" 
class="Vendor" 
column="VendorId" 
lazy="false" 
not-null="true" 
    /> 

Modèle personnalisé Binder:

using System; 

utilisant Test.Web.Mvc; en utilisant Test.Domain;

espace de noms Spoked.MVC { public class ProductUpdateModelBinder: DefaultModelBinder { readonly privé ProductSystem ProductSystem;

public ProductUpdateModelBinder(ProductSystem productSystem) 
    { 
     ProductSystem = productSystem; 
    } 

    protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var product = bindingContext.Model as Product; 
     if (product != null) 
     { 
      product.Category = ProductSystem.GetCategory(new Guid(bindingContext.ValueProvider["Category"].AttemptedValue)); 
      product.Brand = ProductSystem.GetBrand(new Guid(bindingContext.ValueProvider["Brand"].AttemptedValue)); 

      product.ProductVendors.Clear(); 
      if (bindingContext.ValueProvider["ProductVendors"] != null) 
      { 
       string[] productVendorIds = bindingContext.ValueProvider["ProductVendors"].AttemptedValue.Split(','); 
       foreach (string id in productVendorIds) 
       { 
        product.AddProductVendor(ProductSystem.GetVendor(new Guid(id)), 90m); 
       } 
      } 
     } 
    } 
} 

}

Controller:

[AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Update(Product product) 
    { 
     using (var scope = new UnitOfWorkScope()) 
     { 
      //product.ProductVendors.Clear(); 
      _productRepository.Save(product); 
      scope.Commit(); 
     } 
     using (new UnitOfWorkScope()) 
     { 
      IList<Vendor> availableVendors = _productSystem.GetAvailableVendors(product); 
      productDetailEditViewModel = new ProductDetailEditViewModel(product, 
                     _categoryRepository.Select(x => x).ToList(), 
                     _brandRepository.Select(x => x).ToList(), 
                     availableVendors); 
     } 
     return RedirectToAction("Edit", "Products", new {id = product.Id.ToString()}); 
    } 

Le test suivant ne passe cependant:

[Test] 
    [NUnit.Framework.Category("ProductTests")] 
    public void Can_Delete_Product_Vendors_By_Dereferencing() 
    { 
     Product product; 
     using(UnitOfWorkScope scope = new UnitOfWorkScope()) 
     { 
      Console.Out.WriteLine("Selecting..."); 
      product = _productRepository.First(); 
      Console.Out.WriteLine("Adding Product Vendor..."); 
      product.AddProductVendor(_vendorRepository.First(), 0m); 
      scope.Commit(); 
     } 
     Console.Out.WriteLine("About to delete Product Vendors..."); 
     using (UnitOfWorkScope scope = new UnitOfWorkScope()) 
     { 
      Console.Out.WriteLine("Clearing Product Vendor..."); 
      _productRepository.Save(product); // seems to be needed to attach entity to the persistance manager 
      product.ProductVendors.Clear(); 
      scope.Commit(); 
     } 
    } 

dingues ici comme je l'ai presque une solution très agréable entre mvc , les reliures de modèles personnalisés et nhibernate.Juste ne pas voir mes suppressions en cascade. Toute aide grandement appréciée.

Chev

Répondre

0

Si vous voulez que vos entités enfants ont été supprimés lorsque vous parent est supprimé devez définir

cascade="all-delete-orphan" 
l'option

dans la cartographie de collecte. En savoir plus sur les options en cascade que vous pouvez trouver here

+0

Merci pour la réponse. Je n'essaie pas de supprimer le parent, seulement les entités enfants. –

0

Nécessaire d'appeler la méthode de fusion de la session: ISession. Fusionner (produit)

Questions connexes