c# - fluently - Fluido NHibernate en cascada eliminar no funciona
nhibernate c# (2)
Tengo una aplicación de directorio telefónico simple que usa Fluent NHibernate 1.1. En la aplicación, un objeto "Persona" tiene muchos objetos "Número de teléfono". Estoy tratando de eliminar una persona y quiero eliminar en cascada los números de teléfono. Establecí una convención de DefaultCascade.All()
después de leer esta respuesta . Sin embargo, al intentar eliminar el objeto principal aún se produce una excepción: parece que NHibernate está intentando actualizar la tabla secundaria para establecer el ID principal en nulo en lugar de simplemente eliminar el registro:
{"no se pudo eliminar la colección: [Person.PhoneNumbers # 473] [SQL: ACTUALIZAR phone_numbers SET person_id = null DONDE person_id = @ p0]"}
InnerException:
{"No se puede insertar el valor NULL en la columna ''person_id'', tabla ''directory.dbo.phone_numbers''; la columna no permite valores nulos. La ACTUALIZACIÓN falla. / R / nLa declaración ha terminado."}
Mi configuración fluida es:
public static ISessionFactory CreateSessionFactory() {
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["activeConnStr"]].ConnectionString))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Person>()
.Conventions.Add(DefaultCascade.All())
)
.BuildSessionFactory();
}
La clase padre es:
public class Person {
public Person() {
PhoneNumbers = new List<PhoneNumber>();
EmailAddresses = new List<string>();
}
public virtual int Id { get; private set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Company { get; set; }
public virtual IList<PhoneNumber> PhoneNumbers { get; set; }
public virtual IList<string> EmailAddresses { get; set; }
}
La clase infantil (Número de teléfono) es:
public class PhoneNumber {
public virtual string Number { get; set; }
public virtual PhoneNumberType NumberType { get; set; }
public virtual Person Person { get; set; }
}
Mi código para eliminar a una persona es:
public static void DeletePerson(int id) {
using (var session = Dalc.Instance.SessionFactory.OpenSession()) {
using (var trans = session.BeginTransaction()) {
session.Delete(session.Load<Person>(id));
trans.Commit();
}
}
}
¿Qué estoy haciendo mal?
Funciona; Esto es lo que significa cada opción en cascada:
ninguno - no haga ninguna cascada, deje que los usuarios los manejen por sí mismos.
guardar-actualizar : cuando el objeto se guarda / actualiza, verifique las asociaciones y guarde / actualice cualquier objeto que lo requiera (incluido guardar / actualizar las asociaciones en un escenario de muchos a muchos).
eliminar : cuando se elimina el objeto, elimine todos los objetos de la asociación.
delete-huérfano : cuando se elimina el objeto, elimine todos los objetos de la asociación. Además de eso, cuando un objeto se elimina de la asociación y no se asocia con otro objeto (huérfano), también elimínelo.
Todo : cuando un objeto es guardar / actualizar / eliminar, verifique las asociaciones y guarde / actualizar / eliminar todos los objetos encontrados.
all-delete-huérfano : cuando un objeto se guarda / actualiza / elimina, verifique las asociaciones y guarde / actualice / elimine todos los objetos encontrados. Además de eso, cuando un objeto se elimina de la asociación y no se asocia con otro objeto (huérfano), también elimínelo.
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Table("Person");
Id(x => x.Id);
Map(x => x.Name);
HasMany<PhoneNumber>(x => x.PhoneNumberList)
.KeyColumn("PersonId")
.Cascade.All()
.Inverse().LazyLoad();
}
}
No estoy seguro de configurar la parte Fluent, pero recientemente tuve el mismo problema con ActiveRecord.
Debe establecer su asociación, en el lado de la persona, como Inverse = true
.
De mirar la documentación de Primeros pasos ...
Creo que es necesario establecer esto al definir su relación HasMany en persona. Debería verse algo como esto:
public PersonMap()
{
//<...SNIP...>
HasMany(x => x.PhoneNumbers)
.Inverse();
//<...SNIP...>
}