If you look at the sample code below which updates two contact records the first uses late binding and the second use early binding. In the late bound example the ColumnSet class is used to control which fields get returned and updated. If I had the columnset constructor to true then all the fields would be returned and updated.
// Late Bound
QueryByAttribute querybyexpression = new QueryByAttribute(“contact”);
querybyexpression.ColumnSet = new ColumnSet(“telephone1”);
querybyexpression.Attributes.AddRange(“fullname”);
querybyexpression.Values.AddRange(“late bound”);
EntityCollection retrieved = service.RetrieveMultiple(querybyexpression);
var lateContact = retrieved[0];
lateContact[“telephone1”] = “666 6666”;
service.Update(lateContact);
If you look at the audit history for each record only telephone1 field has been changed for the early bound record. The audit history for the early binding example has recorded changes to every field even though they clearly have not changed.
Updates from the UI only every update changed (dirty) fields. I have seen a colleague add a custom field called SDK to each entity they update which they check to determine if workflows and plugins should fire.