Cascade Saves with Fluent NHibernate AutoMapping
Asked Answered
L

5

21

How do I "turn on" cascading saves using AutoMap Persistence Model with Fluent NHibernate?

As in:

I Save the Person and the Arm should also be saved. Currently I get

"object references an unsaved transient instance - save the transient instance before flushing"

public class Person : DomainEntity
{
  public virtual Arm LeftArm { get; set; }
}

public class Arm : DomainEntity
{
  public virtual int Size { get; set; }
}

I found an article on this topic, but it seems to be outdated.

Leventis answered 25/2, 2009 at 17:2 Comment(1)
Would this be done using a convention?Leventis
T
13

This works with the new configuration bits. For more information, see http://fluentnhibernate.wikia.com/wiki/Converting_to_new_style_conventions

//hanging off of AutoPersistenceModel    
.ConventionDiscovery.AddFromAssemblyOf<CascadeAll>()


public class CascadeAll : IHasOneConvention, IHasManyConvention, IReferenceConvention
{
    public bool Accept( IOneToOnePart target )
    {
        return true;
    }

    public void Apply( IOneToOnePart target )
    {
        target.Cascade.All();
    }

    public bool Accept( IOneToManyPart target )
    {
        return true;
    }

    public void Apply( IOneToManyPart target )
    {
        target.Cascade.All();
    }

    public bool Accept( IManyToOnePart target )
    {
        return true;
    }

    public void Apply( IManyToOnePart target )
    {
        target.Cascade.All();
    }
}
Throaty answered 19/3, 2009 at 21:4 Comment(1)
Thanks. I actually used Kristoffers shorter example but I am sure this one works tooSweeting
M
13

Updated for use with the the current version:

public class CascadeAll : IHasOneConvention, IHasManyConvention, IReferenceConvention
{
    public void Apply(IOneToOneInstance instance)
    {
        instance.Cascade.All();
    }

    public void Apply(IOneToManyCollectionInstance instance)
    {
        instance.Cascade.All();
    }

    public void Apply(IManyToOneInstance instance)
    {
        instance.Cascade.All();
    }
}
Mandler answered 15/3, 2010 at 14:26 Comment(1)
For "public void Apply(IOneToManyCollectionInstance instance) ", I also find it useful to have "instance.inverse();" in addition to "instance.Cascade.All()."Remote
A
4

The easiest way I've found to do this for a whole project is to use DefaultCascade:

.Conventions.Add( DefaultCascade.All() );     

Go to "The Simplest Conventions" section on the wiki, for this, and a list of others.

Here's the list from the Wiki:

Table.Is(x => x.EntityType.Name + "Table")
PrimaryKey.Name.Is(x => "ID")
AutoImport.Never()
DefaultAccess.Field()
DefaultCascade.All()
DefaultLazy.Always()
DynamicInsert.AlwaysTrue()
DynamicUpdate.AlwaysTrue()
OptimisticLock.Is(x => x.Dirty())
Cache.Is(x => x.AsReadOnly())
ForeignKey.EndsWith("ID")

A word of warning - some of the method names in the Wiki may be wrong. I edited the Wiki with what I could verify (i.e. DefaultCascade and DefaultLazy), but can't vouch for the rest. But you should be able to figure out the proper names with Intellisense if the need arises.

Aureliaaurelian answered 3/11, 2011 at 22:15 Comment(2)
I'd love to see that link, but it's deadSupersession
@Joel: looks like the new wiki is here: github.com/jagregory/fluent-nhibernate/wiki/ConventionsRasping
R
3

The Convention Method Signatures have changed. For the new answer that does exactly what this question asks see THIS QUESTION.

Rimskykorsakov answered 11/2, 2010 at 17:54 Comment(0)
P
1

You can also make cascading the default convention for all types. For example (using the article you linked to as a starting point):

autoMappings.WithConvention(c =>  
  {  
    // our conventions
    c.OneToOneConvention = o => o.Cascade.All();
    c.OneToManyConvention = o => o.Cascade.All();
    c.ManyToOneConvention = o => o.Cascade.All();
  });
Pothole answered 26/2, 2009 at 17:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.