В дополнение к предложению @ GMB другой альтернативой является просто наличие других таблиц контактов. То, что у Locations и Customers есть контакты, и только потому, что они изначально имеют одинаковые атрибуты, не означает, что они должны храниться в одной таблице.
Более эффективно хранить их отдельно вот так, если вы не собираетесь запрашивать все контакты. И схема для трех со временем может расходиться.
Они могут даже использовать суперкласс NotMapped для Contact в приложении, если вы хотите писать общие c логики для типов контактов.
EG
CREATE TABLE [dbo].[CustomerContacts] (
[CustomerId] INT not null references Customer on delete cascade,
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (80) NULL,
[Email] NVARCHAR (80) NULL,
[Phone] NVARCHAR (80) NULL,
[Title] NVARCHAR (80) NULL,
[Address] NVARCHAR (120) NULL,
constraint pk_CustomerContacts primary key (CustomerId,Id)
);
CREATE TABLE [dbo].[ProviderContacts] (
[ProviderId] INT not null references Provider on delete cascade,
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (80) NULL,
[Email] NVARCHAR (80) NULL,
[Phone] NVARCHAR (80) NULL,
[Title] NVARCHAR (80) NULL,
[Address] NVARCHAR (120) NULL,
constraint pk_ProviderContacts primary key (ProviderId,Id)
);
CREATE TABLE [dbo].[LocationContacts] (
[LocationId] INT not null references Location on delete cascade,
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (80) NULL,
[Email] NVARCHAR (80) NULL,
[Phone] NVARCHAR (80) NULL,
[Title] NVARCHAR (80) NULL,
[Address] NVARCHAR (120) NULL,
constraint pk_LocationContacts primary key (LocationId,Id)
);