使用nhibernate删除未引用的子记录

时间:2009-09-07 12:10:05

标签: asp.net-mvc nhibernate

我正在使用nhibernate作为orm(ncommon框架)的mvc应用程序

我有父/子实体:产品,供应商& ProductVendors和它们之间的一对多关系,Product与ProductVendors集合Product.ProductVendors。

我目前正在检索一个Product对象并急切地加载这些子对象并将它们发送到我的asp.net mvc客户端。

然后,用户将修改供应商列表并重新发布更新的产品。我正在使用自定义模型绑定器来生成修改后的Product实体。我可以更新产品并插入新的ProductVendors。

我的问题是,在指定Product.ProductVendors.Clear()并调用_productRepository.Save(product)时,不会级联删除已取消引用的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="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"
   />

自定义模型Binder:

using System;

使用Test.Web.Mvc; 使用Test.Domain;

命名空间Spoked.MVC {     public class ProductUpdateModelBinder:DefaultModelBinder     {         private readonly 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);
                }
            }
        }
    } 
}

}

控制器:

    [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()});
    }

以下测试确实通过了:

 [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();
        }
    }

坚持到底,因为我在mvc,自定义模型绑定器和nhibernate之间几乎有一个非常好的解决方案。只是没有看到我的删除级联。非常感谢任何帮助。

CHEV

2 个答案:

答案 0 :(得分:0)

如果您希望删除父级时删除子实体,则需要设置

cascade="all-delete-orphan"
集合映射中的

选项。有关级联选项的更多信息,请参阅here

答案 1 :(得分:0)

需要调用会话的Merge方法:ISession。合并(产品)