After defeat to Lyon a fortnight ago, it had looked like being another frustrating night for City in Group F until Silva pounced on a defensive mistake three minutes from time.
Pep Guardiola’s side had got off to a dreadful start, conceding after just 44 seconds when Ishak Belfodil opened the scoring, but Sergio Aguero quickly equalised.
Leroy Sane was controversially denied a penalty in the second half but City otherwise found the going tough against the determined Germans.
City, with Aymeric Laporte at left-back, were rocked in the first minute. Nicolas Otamendi and Vincent Kompany both seemed unsure of their positioning as Belfodil raced onto a brilliant through-ball from Florian Demirbay and lashed home.
City looked ragged but responded quickly as Silva released Sane. The German, perhaps with a point to prove in his home country after recent criticism, pulled back for Aguero and the striker, fit after a foot injury, made no mistake.
Hoffenheim were not fazed and continued to run at the City defence. Pavel Kaderabek burst down the left and went down under pressure from Kyle Walker but Slovenian referee Damir Skomina dismissed his penalty appeal.
City turned defence into attack quickly as Silva played Raheem Sterling through but the England forward was denied by the legs of Oliver Baumann, who also made a brilliant save to keep out Aguero’s attempt to find the top corner.
Despite giving the ball away on numerous occasions, City dominated for a spell and Kompany threatened at a corner, only to be penalised for a push. Aguero missed the target with an acrobatic effort after another good run by Sane and also shot narrowly over following a long Ederson punt.
Guardiola – only just back from a touchline ban – was spoken to by Skomina for protesting when Silva was prevented from taking a quick throw. Yet that was little compared to the frustration Guardiola felt when Laporte allowed Belfodil through after under-hitting a back pass. It required a good save from Ederson to rescue City.
City also made an uncertain start to the second half as Florian Grillitsch’s long-range effort flew just over and they survived another scare when Ederson missed a header attempting to clear a long ball from Baumann. Sane got back to prevent former Leicester striker Andrej Kramaric shooting into an empty goal.
Fernandinho did fire at Baumann but City lacked control and Walker was booked for a bad challenge on Kaderabek.
Bernardo Silva came off the bench to give City another dimension but Aguero headed straight at Baumann from a cross from the Portuguese.
City felt they should have had a penalty 18 minutes from time when Sane appeared to be caught by Baumann after Bernardo Silva again opened Hoffenheim up but, much to their frustration, nothing was given.
Time began to run out for the visitors but David Silva lifted their spirits by smashing home after Stefan Posch failed to clear Bernardo Silva’s cross.