سؤال

I have a model contains a list of the same model as a many-to-many relationship, and I have a problem when deleting an item of this model type when having a relation with another item.

This error happened because of a foreign key error.

The model code is as the following:

public class Employee : ModelBase
{
    public virtual string FullName { get; set; }

    public virtual IList<Employee> Managers { get; set; }

}

The mapping file is as follows

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="Models"
                   namespace="Models"
                   default-lazy="false">
  <class name="Employee">
    <id name ="Id">
      <generator class="native" />
    </id>

    <property name="FullName"></property>

    <bag name="Managers">
      <key column="Id" />
      <many-to-many class="Employee"/>
    </bag>

  </class>
</hibernate-mapping>

Suppose I have created two employees, emp1, emp2, and then I have added emp2 to Managers list in emp1.

If I want to delete emp1, I have the same error, but I can easily resolve it by clearing the managers list. but if I want to delete emp2, I cannot loop for every employee to see if the Managers list contains this employee!! it will reduce the performance.

My Question, is there an implicit way for nhibernate to handle this issue?

EDIT1 :

My delete statement is

var queryString = string.Format("delete {0} where Id = :id",
    typeof(T));
session.CreateQuery(queryString)
    .SetParameter("id", modelId)
    .ExecuteUpdate();
هل كانت مفيدة؟

المحلول

Well, either we've got here the parent-child hierarchy, (x)or many-to-many relation.

I. In case of many-to-many, we are missing

  • the pairing table
  • the second, reverted view on this relationship.

The model we have is providing the up view: Managers, and should also provide the down view: Subordinates.

<bag name="Managers" table="ManagerSubOrdinates" >
  <key column="ManagerId" />
  <many-to-many class="Employee" column="SubordinateId"/>
</bag>

<bag name="Subordinates" table="ManagerSubOrdinates" inverse="true" >
  <key column="SubordinateId" />
  <many-to-many class="Employee" column="ManagerId"/>
</bag>

Now, we mapped both ends of the pairing table/relation ManagerSubOrdinates. If we will delete the Employee, the related records will be removed as well - but just from the pairing table. Not the related Managers or Subordinates

Finally the Deletion.

Now, when we do have the mapping in place, the correct way how to delete is like this

// load the Employee with ID == 1 into the ISession
var employee = session.Get<Employee>(1); // id 1
// pass this instance into the Delete 
session.Delete(employee);

This will instruct NHibernate to properly remove all records from pairing table (both mappings) and then delete the Employee record itself

(not sure here) II. If this is in fact, the parent-child relation, we have to correct the mapping this way:

<bag name="Subordinates">
  <key column="ManagerId" />
  <many-to-many class="Employee"/>
</bag>
<many-to-one class="Employee" Name="Manager" column="ManagerId" >

Here I am just guessing (more Subordinates, one Manager), but The essence is in the column name ManagerId. In most scenarios, the key column does not have value "Id" which usually referes to the table Primary key, not the foreign key...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top