Question

I have this problem where I have a one-to-many relationship and I have to be able to delete the parent entity without it's children being deleted, nor their foreign key column set to NULL. But whenever I try deleting a parent, I get the foreign key constraint violation exception.

NHibernate.Exceptions.GenericADOException: could not execute update query[SQL: delete from [Customer]] ---> System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "FK7867CB245055157F"

I have a similar one-to-one relationship, where I have to be able to delete the entity on one end without the foreign key on the other end to be set to NULL and I solved this problem successfully by using NotFound.Ignore(). I have found several answers suggesting exactly this solution, but it seems to have no effect at all. I use my mapping to build the database BTW.

Here are my entities and mappings:

public class User : Entity
{
    ...
    public virtual Customer Customer { get; set; }
    ...
}
public class Customer : Entity
{
    ...
    public virtual string CustomerNumber { get; set; }
    public virtual User User { get; set; }
    public virtual IList<Vehicle> Vehicles { get; set; }
    ...
}
public class Vehicle : Entity
{
    ...
    public virtual string SerialNumber { get; set; }
    public virtual Customer Customer { get; set; }
    ...
}

I'm using AutoMapping and overrides:

public class UserMappingOverride : IAutoMappingOverride<User>
{
    public void Override(AutoMapping<User> mapping)
    {
        ...
        mapping.References(u => u.Customer).Column("CustomerNumber").NotFound.Ignore();
    }
}
public class CustomerMappingOverride : IAutoMappingOverride<Customer>
{
    public void Override(AutoMapping<Customer> mapping)
    {
        mapping.Id(u => u.Kundenummer).GeneratedBy.Assigned().Not.Nullable();
        mapping.HasOne(u => u.User).PropertyRef(c => c.Customer);
        mapping.HasMany(u => u.Vehicles).KeyColumns.Add("CustomerNumber")
            .Cascade.None()
            .Inverse();
    }
}
public class VehicleMappingOverride : IAutoMappingOverride<Vehicle>
{
    public void Override(AutoMapping<Vehicle> mapping)
    {
        mapping.Id(u => u.SerialNumber).GeneratedBy.Assigned().Not.Nullable();
        mapping.References(u => u.Customer).Column("CustomerNumber").NotFound.Ignore();
    }
}

As said, in the one-to-one relationship, in the mapping of User I use NotFound.Ignore(), which does as promised - allows me to delete a Customer without firing a constraint violation exception and still keep the values of "CustomerNumber" in the User table intact. The mapping of the relationship between the User and the Customer entities, simply does not produce a foreign key constraint in the database when the database is built from the mapping.

But the same thing doesn't work for my one-to-many relationship. Although the mapping is almost the same as my one-to-one relationship, and I use NotFound.Ignore() as suggested in similar questions here, this relationship still produces a foreign key constraint and I get a constraint violation exception when trying to delete a Customer. The only work-around is to manually delete the FK in the database or modify it by setting Enforce Foreign Key Constraint to False.

How can I get NHibernate to either not create this Foreign key constraint, or setting the Enfore Foreign Key Constraint to False, when building the database?

Best Regards - Nikolaj

BTW: I'm not interested in comments about the overall design of the entities and relationships. They're designed like this based on constraints from the source of data, and this is the only plausible workaround. :-) I've found that a lot of answers in similar posts, focus on the design rater then of the question at hand.

Était-ce utile?

La solution 2

Firo's answer pointed me in the right direction as how to get rid of the FK constraint. Adding .ForeignKey("none") to the Vehicle mapping didn't do it though. But adding a similar property to the Customer mapping solved my problem.

So the solution became:

mapping.HasMany(u => u.Vehicles).ForeignKeyConstraintName("none")

Autres conseils

you can not work around the FK in the database. My guess is that there is no FK from User to Customer. If you create the Schema from mappings then you'll need to disable the creation of the FK with mapping.References(u => u.Customer).ForeignKey("none");

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top