Free NHibernate - Cascade All Delete An orphan does nothing when removed

I have two simple classes that reference each other as a one-to-many relationship, defined below:

public class Project { public virtual int Id { get; set; } public virtual string Name { get; set; } public virtual IList<Document> Documents { get; set; } } public class Document { public virtual int Id { get; set; } public string FileName { get; set; } } 

And my mappings are defined as:

 public class ProjectMapping : ClassMap<Project> { public ProjectMapping() { Table("Projects"); Id(x => x.Id).Column("Project_Id").GeneratedBy.TriggerIdentity(); HasMany(x => x.Documents) .Table("Documents") .KeyColumn("Document_Project_Id") .Cascade.AllDeleteOrphan() .Not.KeyNullable(); Map(x => x.Name).Column("Project_Name"); } } public class DocumentMapping : ClassMap<Document> { public DocumentMapping() { Table("Documents"); Id(x => x.Id).Column("Document_Id").GeneratedBy.TriggerIdentity(); Map(x => x.FileName).Column("Document_File_Name"); } } 

Everything seems to be working fine, adding / updating documents and calling session.Save (project) reflects the correct changes in my database, however, if I want to remove a document from the list of documents associated with the project and the .Save (project) remote call session the document is never deleted from the database.

Any ideas why everything else will work except deletion?

EDIT: My MVC 4 project is configured using Fluent NHibernate as follows:

 public class SessionFactoryHelper { public static ISessionFactory CreateSessionFactory() { var c = Fluently.Configure(); try { //Replace connectionstring and default schema c.Database(OdbcConfiguration.MyDialect. ConnectionString(x => x.FromConnectionStringWithKey("DBConnect")) .Driver<NHibernate.Driver.OdbcDriver>() .Dialect<NHibernate.Dialect.Oracle10gDialect>()) .ExposeConfiguration(cfg => cfg.SetProperty("current_session_context_class", "web")); c.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Project>()); c.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Document>()); } catch (Exception ex) { Log.WriteLine(ex.ToString()); } return c.BuildSessionFactory(); } } public class MvcApplication : System.Web.HttpApplication { public static ISessionFactory SessionFactory { get; private set; } protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); AuthConfig.RegisterAuth(); SessionFactory = SessionFactoryHelper.CreateSessionFactory(); } protected void Application_BeginRequest(object sender, EventArgs e) { var session = SessionFactory.OpenSession(); CurrentSessionContext.Bind(session); } protected void Application_EndRequest(object sender, EventArgs e) { var session = CurrentSessionContext.Unbind(SessionFactory); session.Dispose(); } } 

My repository is defined as follows:

 public class Repository<T> : IRepository<T> { public virtual ISession Session { get { return MvcApplication.SessionFactory.GetCurrentSession(); } } public T FindById(int iId) { return Session.Get<T>(iId); } public void Save(T obj) { using (var transaction = Session.BeginTransaction()) { try { Session.Save(obj); transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); Log.WriteLine(ex.ToString()); } } } public T SaveOrUpdate(T obj) { using (var transaction = Session.BeginTransaction()) { try { Session.SaveOrUpdate(obj); transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); Log.WriteLine(ex.ToString()); } } return obj; } public T Update(T obj) { using (var transaction = Session.BeginTransaction()) { try { Session.Update(obj); transaction.Commit(); } catch (Exception ex) { transaction.Rollback(); Log.WriteLine(ex.ToString()); } } return obj; } } 

I have 2 actions defined in my ProjectController, as follows:

 private IRepository<Project> repository; public ProjectsController() { repository = new Repository<Project>(); } public ActionResult Edit(int iId) { Project project = repository.FindById(iId); if (project == null) return HttpNotFound(); return View(project); } [HttpPost] public ActionResult Edit(Project project) { project = repository.Update(project); return View(project); } 

If I have to delete a document in my first action (without HttpPost):

 project.Documents.RemoveAt(0); repository.Update(project); 

The correct row is deleted from the database. However, if I have to do the same in action with the HttpPost attribute, the string is never deleted.

It should also be noted that if I add a document to the project. Documents in action with the HttpPost attribute, repository.Update (project) successfully adds a row with the correct foreign key reference for the project. This only happens when a document is deleted.

+4
source share
2 answers

Cascading setup seems correct. The above question may be elsewhere:

however, if I have to remove a document from the list of documents associated with the project

It is assumed that this is a flash mode session or there is no explicit call to update the parent Project object that was previously disconnected. Convince:

First, Flush() called. If the Project instance is still stored in the session, the default paint behavior can be changed. (e.g. session.FlushMode = FlushMode.Never; or Commit without a transaction ...)

 // 1) checking the explicit Flush() project.Documents.Remove(doc); Session.Flush(); // this will delete that orphan 

The second may be an instance of Project that needs an explicit update call.

 // 2) updating evicted project instance project.Documents.Remove(doc); Session.Update(project); //Session.Flush(); // Session session.FlushMode = FlushMode.Auto 

In this case (only), the inverse parameter will help reduce one trip to the database using the UPDATE statement, dropping the link to doc.Project = null , and then executing DELETE.

+2
source

Have you tried adding .Inverse to your HasMany ?

Also, I am not familiar with Not.KeyNullable . I do not think this is necessary here.

+2
source

All Articles