Andrew
Andrew

Reputation: 905

How to prevent NHibernate from calling Flush during a session that only reads data

When I run this code, the List method causes a flush of the Developer. I don't want this to happen.

Developer developer = null;
IEnumerable<Language> languages = null;
using (var session = this.SessionFactory.OpenSession())
using (var trx = session.BeginTransaction())
{
    developer = session.Get<Developer>(id);
    languages = session.CreateCriteria<Language>().List<Language>();
}

If I swap the lines inside the using so that the languages are retrieved first, then the developer is not flushed. But I don't want to have to remember to do that unless there's a good reason.

Do I need to change my mapping? Here's what it looks like now:

class DeveloperMap : ClassMap<Developer>
{
    public DeveloperMap()
    {
        Table("Developers");
        Id(x => x.Id).GeneratedBy.Identity();
        Map(x => x.FirstName);
        Map(x => x.LastName);
        References(x => x.FavoriteLanguage).Cascade.None();
        HasManyToMany(x => x.AssignedProjects)
            .Cascade.None()
            .Table("DevelopersProjects")
            .FetchType.Join();
    }
}

Here's the Developer class too, just in case that helps.

public class Developer
{
    public virtual int? Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual Language FavoriteLanguage { get; set; }
    public virtual IList<Project> AssignedProjects { get; protected internal set; }
}

Upvotes: 1

Views: 1008

Answers (2)

rae1
rae1

Reputation: 6144

I've noted on several occasions that wrapping read-only operations inside a Transaction tends to cause undesired effects. As Diego mentions, the Flush might be caused by an incorrect mapping.

I understand there might be some performance issues with this, as noted here. However, if you are only reading you shouldn't need a using(Transaction) block.

Try removing it, as such,

using (var session = this.SessionFactory.OpenSession())
{
    developer = session.Get<Developer>(id);
    languages = session.CreateCriteria<Language>().List<Language>();
}

Upvotes: 1

Diego Mijelshon
Diego Mijelshon

Reputation: 52735

If you aren't changing data, there shouldn't be a flush at all, unless you have a ghost (incorrect mapping that is forcing an unnecessary update). I suggest that you verify (with a profiler, checking the SQL log, etc) what is being flushed exactly.

To prevent automatic flushes, just set session.FlushMode to anything other than Auto (the default) or Always. Commit is, in my opinion, the most practical behavior.

Upvotes: 3

Related Questions