It seems to me rather flaky to rely on the text of the message when it already has an error code. While there are some other issues with the pattern as outlined by the other answers at the very least I would search for "23503" rather than "foreign key constraint". Otherwise what happens if the user's install of the database is in a different culture, or an updated version of the server changes the text of the message?
Actually looking at some online documentation for the exception class you are using it looks like there is even a Code property, this would be much faster and more reliable to compare against than the message property.
Final thought...
I agree with Van that you should be throwing a more concrete exception when the constraint is broken, but also you shouldn't be throwing a base Exception when the error is something else. Firstly is is never good practice to throw the base exception class since it doesn't give the client code any easily testable information about what the error is. Secondly you are losing a lot of information, all the extra properties that the NpgsqlException implements plus the stack trace. I'd replace the throwing with something like:
if (ex.Message.Contains("foreign key constraint"))
throw new ConstraintException("Cannot delete this, this record is already referenced on other record(s)");
else
throw;
Basically if you aren't going to do anything productive with the exception then don't touch it, you never know what information code back up the call stack may need.