开发者

nHibernate Cascade AllDeleteOrphan: Why is NH deleting each collection item individually

开发者 https://www.devze.com 2023-04-01 17:11 出处:网络
When I\'m clearing a childcollection like this table.Indizes.Clear(); session.Flush(); then NH generates a delete SQL for each item which was in the collection:

When I'm clearing a childcollection like this

table.Indizes.Clear();
session.Flush();

then NH generates a delete SQL for each item which was in the collection:

DELETE FROM x_inddef WHERE ind_name = 'IDX_ADRKONZ_CODE' AND tbl_name = 'ADRESSE' DELETE FROM x_inddef WHERE ind_name = 'IDX_ADRKUND_EXT' AND tbl_name = 'ADRESSE'

...

Why isn't it generating a statement like this?

DELETE FROM x_inddef WHERE tbl_name = 'ADRESSE'

Is something wrong with my mappings, or is this just the normal behaviour?

Simplified Code with the fluent Mapping:

public class Table
{
    public virtual string Name {get;set;
    public virtual IList<Index> Indizes { get; set; }
}

public class TableOverride : IAutoMappingOverride<Table>
{
    public void Override(AutoMapping<Table> mapping)
    {
        mapping.Table("x_tables");
        mapping.Id(x => x.Name, "tbl_name");
        mapping.HasMany(x => x.Indizes).KeyColumn("tbl_name").Inverse().Cascade.AllDel开发者_Python百科eteOrphan();
    }
}

public class Index
{
    public virtual string Name { get; set; }
    public virtual Table Table { get; set; }

    public override bool Equals(object obj)
    {
        //...
    }

    public override int GetHashCode()
    {
        //...
    }
}

public class IndexOverride : IAutoMappingOverride<Index>
{
    public void Override(AutoMapping<Index> mapping)
    {
        mapping.Table("x_inddef");
        mapping.CompositeId().
            KeyProperty(x => x.Name, "ind_name").
            KeyReference(x => x.Table, "tbl_name");
    }
}


You should enable batch updates option with nhibernate

First of all set adonet.batch_size property in your NHibernate configuration to value, greater then zero.

And then mark each hasMany collection with .BatchSize(xxx)

mapping.HasMany(x => x.Indizes)
   .BatchSize(25)
   .KeyColumn("tbl_name")
   .Inverse()
   .Cascade.AllDeleteOrphan();

I guess this should help


One-shot deletes do not work with inverse=true. Allocating a new instance of the index collection with 0 elements and dereferencing the old one throws an exception as Nhibernate expects to manage the collection. It seems the only way out is to use hql.

Check section 19.5.4 in the documentation - http://www.nhforge.org/doc/nh/en/index.html


All-delete-orphan means that your child collection would be deleted if you delete the parent element.
meaning- if you delete a Table object, than DELETE FROM x_inddef WHERE tbl_name =... would be issued.
calling Clear() is just a shorthand for deleting all the objects in a collection, but the Table object itself remains intact.


Another possible solution is to use HQL:

session.CreateQuery("DELETE Index i WHERE i.Table.Name = :tblName")
    .SetString( "tblName", "MyTable" )
    .ExecuteUpdate();
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号