I edited for another option at the end.
If I get it right, the group sends the subgroup, ie the subgroup is tied to the group. The ClientId left out, because the foreign key is in the wrong entity and ClientId will never be the primary key candidate in another entity, read the options below.
public abstract class Base
{
[Key]
public int Id { get; set; }
public int ClienteId { get; set; }
}
public class Grupo : Base
{
public string Nome { get; set; }
}
public class SubGrupo : Base
{
public int GrupoId { get; set; }
public string Nome { get; set; }
[ForeignKey("GrupoId")]
public Grupo Grupo { get; set; }
}
Note that if you include foreing key in ClientId EF will complain about CASCADE cyclic because it falls on both Group and Subgroup classes, in which case you can either warn EF not to do CASCADE or move the ClientId to Group.
There are polymorphic means of doing this in the DB, but stay on the other occasion.
I see restrictions this way
public abstract class Base
{
[Key]
public int Id { get; set; }
}
public class Grupo : Base
{
public string Nome { get; set; }
public int ClienteId { get; set; }
[ForeignKey("ClienteId")]
public Cliente Cliente { get; set; }
}
public class SubGrupo : Base
{
public int GrupoId { get; set; }
public string Nome { get; set; }
[ForeignKey("GrupoId")]
public Grupo Grupo { get; set; }
}
public class Cliente
{
[Key]
public int Id { get; set; }
}
What generates these schemes:
CREATE TABLE [dbo].[Grupoes] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Nome] NVARCHAR (MAX) NULL,
[ClienteId] INT NOT NULL,
CONSTRAINT [PK_dbo.Grupoes] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.Grupoes_dbo.Clientes_ClienteId] FOREIGN KEY ([ClienteId]) REFERENCES [dbo].[Clientes] ([Id]) ON DELETE CASCADE
);
CREATE TABLE [dbo].[SubGrupoes] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[GrupoId] INT NOT NULL,
[Nome] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.SubGrupoes] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.SubGrupoes_dbo.Grupoes_GrupoId] FOREIGN KEY ([GrupoId]) REFERENCES [dbo].[Grupoes] ([Id]) ON DELETE CASCADE
);
The rest is JOIN.
I'll include a Many-To-Many option to make it more complete.
public abstract class Base
{
[Key]
public int Id { get; set; }
}
public class Grupo : Base
{
public string Nome { get; set; }
public ICollection<Cliente> Clientes { get; set; }
public Grupo()
{
Clientes = new Collection<Cliente>();
}
}
public class SubGrupo : Base
{
public int GrupoId { get; set; }
public string Nome { get; set; }
[ForeignKey("GrupoId")]
public Grupo Grupo { get; set; }
}
public class Cliente
{
[Key]
public int Id { get; set; }
public ICollection<Grupo> Grupos { get; set; }
public Cliente()
{
Grupos = new Collection<Grupo>();
}
}
EF creates the intermediate table with the foreign and primary composite keys:
CREATE TABLE [dbo].[GrupoClientes] (
[Grupo_Id] INT NOT NULL,
[Cliente_Id] INT NOT NULL,
CONSTRAINT [PK_dbo.GrupoClientes] PRIMARY KEY CLUSTERED ([Grupo_Id] ASC, [Cliente_Id] ASC),
CONSTRAINT [FK_dbo.GrupoClientes_dbo.Grupoes_Grupo_Id] FOREIGN KEY ([Grupo_Id]) REFERENCES [dbo].[Grupoes] ([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.GrupoClientes_dbo.Clientes_Cliente_Id] FOREIGN KEY ([Cliente_Id]) REFERENCES [dbo].[Clientes] ([Id]) ON DELETE CASCADE
);