Did you try making the entities persistent with the setPersistent() method when they are tamed?
If you look at EntityLiving there are some related fields/methods:
- canDespawn() which defaults to true
- despawnEntity() which looks at a couple things including distance, the canDespawn() and also
- isPersistenceRequired which can be set with the enablePersistence() method, and this also is returned for the isNoDespawnRequired() method.
If you look at the despawnEntity() method and trace the logic, you'll see that simply setting the persistence with enablePersistence() method will prevent despawning.
That should help a fair bit because entities despawn even when chunks are loaded without persistence.
Now I don't think persistence really helps if the chunk is actually unloaded. But it might so maybe Draco18s or diesieben07 know more details about that. You could force the entities to stay loaded by handling the chunk unload event and directly manipulating the world unloadedEntitiesList, but I think that would be a problem to have entities loaded without the chunk. But again others might know better.
I would start by ensuring your entities are persistent. If there is still an issue, then what I would do is create a capability for the player that contains a List of the EntityDogs that have been tamed. I think you would actually just keep some information about the dogs and when you want to whistle them you would find the ones in the world and bring them, and then all the ones that are missing you'd have to re-construct. But I'm guessing at this point.