nhibernate-core icon indicating copy to clipboard operation
nhibernate-core copied to clipboard

Bulk Update using UpdateBuilder

Open satishviswanathan opened this issue 3 years ago • 1 comments

I'm trying to do a bulk update as shown below.

 await _session.Query<Employee>()
                .Where(x => x.Name.StartsWith("sa"))
                .UpdateBuilder().Set(y => y.Score.Performance, 10)
                .UpdateAsync(ct).ConfigureAwait(false);

This is what I'm seeing in the error. Seems like the join between Employee and Score is not working.

NHibernate: update Employee set Score.Performance=:p0 where Name like (:p1||'%');:p0 = 10 [Type: Int32 (0:0:0)], :p1 = 'sa' [Type: String (0:0:0)]

Models

  public class Employee 
  {
      public Employee()
      {
          
      }
      public virtual string Name { get; set; }
      public virtual string Address { get; set; }
      public virtual Score Score { get; set; }
  }

  public class Score 
  {
      public virtual Employee EmployeeId { get; set; }
      public virtual int Performance { get; set; }

  }

Mapping

   public sealed class EmployeeMap
    {
        public EmployeeMap() : base("Employee", "Id")
        {
           Id(x => x.Id);
            Map(x => x.Name);
            Map(x => x.Address);
            HasOne(x => x.DeptId);
           HasOne(x => x.Score).PropertyRef(r=>r.EmployeeId).Fetch.Join().ForeignKey("EMPLOYEEID").Cascade.All();
           DynamicUpdate();
            DynamicInsert();

            Table("Employee");
        }

}

public class ScoreMap
{
    public ScoreMap() 
    {
       Id(x => x.Id);
        References(x => x.EmployeeId).Columns("EMPLOYEEID").Cascade.All();
        Map(x => x.Performance);
        DynamicUpdate();
        DynamicInsert();

        Table("Score");
    }
}

Not sure what i'm missing here.

satishviswanathan avatar Dec 08 '21 21:12 satishviswanathan

Not sure what i'm missing here.

Updates on association entities (y.Score.Performance) are not supported.

As a workaround you can try to rewrite this DML using subquery. Something like:

IQueryable<Score> scoreToUpdateSubQuery = session.Query<Employee>().Where(x => x.Name.StartsWith("sa")).Select(e => e.Score);
await session.Query<Score>()
  .Where(e => scoreToUpdateSubQuery.Contains(e))
  .UpdateBuilder().Set(s => s.Performance, 10)
  .UpdateAsync(ct).ConfigureAwait(false);

bahusoid avatar Jan 21 '22 13:01 bahusoid