Cascade Saves with Fluent NHibernate AutoMapping

2019-02-01 08:26发布

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.

5条回答
Root(大扎)
2楼-- · 2019-02-01 08:49

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();
    }
}
查看更多
迷人小祖宗
3楼-- · 2019-02-01 08:58

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();
    }
}
查看更多
神经病院院长
4楼-- · 2019-02-01 09:03

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();
  });
查看更多
走好不送
5楼-- · 2019-02-01 09:07

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.

查看更多
劫难
6楼-- · 2019-02-01 09:08

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

查看更多
登录 后发表回答