Votre contexte est similaire à ce
public DbSet<Activity> Activity { get; set; }
public DbSet<DataCaptureActivity> DataCaptureActivities { get; set; }
public DbSet<MasterDataCaptureActivity> MasterDataCaptureActivities { get; set; }
Ce que vous dites sur le plan conceptuel à EF est que DataCaptureActivity
est un Activity
et que MasterDataCaptureActivity
est un Activity
. Sur la base de données, vous créez toutes les trois entités.
Avec ce modèle, la déclaration
context.Activities.ToList();
récupérer toute l'Activities
(l'union des trois ensembles). Pour le faire avec votre modèle, EF sur la base de données va créer la table d'activité avec un discriminateur. Les structures de table seront ce (regardez 1-1 relations):
ExecuteNonQuery==========
CREATE TABLE [Activity] (
[Id] int not null identity(1,1)
, [ActivityType] int not null
, [Description] text null
, [Title] varchar(100) null
, [Discriminator] varchar(128) not null
);
ALTER TABLE [Activity] ADD CONSTRAINT [PK_Activity_7ea65be8] PRIMARY KEY ([Id])
ExecuteNonQuery==========
CREATE TABLE [DataCaptureActivities] (
[Id] int not null
, [DataCaptureActivityType] int not null
);
ALTER TABLE [DataCaptureActivities] ADD CONSTRAINT [PK_DataCaptureActivities_7ea65be8] PRIMARY KEY ([Id])
ExecuteNonQuery==========
CREATE TABLE [MasterDataCaptureActivities] (
[Id] int not null
, [SomeOtherField] text null
);
ALTER TABLE [MasterDataCaptureActivities] ADD CONSTRAINT [PK_MasterDataCaptureActivities_7ea65be8] PRIMARY KEY ([Id])
ExecuteNonQuery==========
CREATE INDEX [IX_Id] ON [DataCaptureActivities] ([Id])
ExecuteNonQuery==========
CREATE INDEX [IX_Id] ON [MasterDataCaptureActivities] ([Id])
ExecuteNonQuery==========
ALTER TABLE [DataCaptureActivities] ADD CONSTRAINT [FK_DataCaptureActivities_Activity_Id] FOREIGN KEY ([Id]) REFERENCES [Activity] ([Id])
ExecuteNonQuery==========
ALTER TABLE [MasterDataCaptureActivities] ADD CONSTRAINT [FK_MasterDataCaptureActivities_Activity_Id] FOREIGN KEY ([Id]) REFERENCES [Activity] ([Id])
En outre, cette déclaration
using (var context = new Context(GetConnection()))
{
context.DataCaptureActivities.Add(new DataCaptureActivity() {Description = "Description"});
context.SaveChanges();
}
générera ce déclarations DML (2 états d'insertion !!!)
ExecuteDbDataReader==========
insert into [Activity]([ActivityType], [Description], [Title], [Discriminator])
values (@p0, @p1, null, @p2);
select [Id]
from [Activity]
where [Id] = @@identity
@p0 = 0
@p1 = Description
@p2 = DataCaptureActivity
ExecuteNonQuery==========
insert into [DataCaptureActivities]([Id], [DataCaptureActivityType])
values (@p0, @p1);
@p0 = 1
@p1 = 0
La solution pour cibler vos tables
Vous devez modifier votre modèle en indiquant que DataCaptureActivities et MasterDataCaptureActivities ne sont pas des activités.
Par exemple:
public abstract class BasePoco
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
}
public class BaseActivity : BasePoco
{
public ActivityType ActivityType { get; set; }
[MaxLength(1000)]
public string Description { get; set; }
}
[Table("Activity")]
public class Activity : BaseActivity
{
}
public class DataCaptureActivityBase : BaseActivity
{
[MaxLength(100)]
public string Title { get; set; }
}
[Table("DataCaptureActivities")]
public class DataCaptureActivity : DataCaptureActivityBase
{
public virtual DataCaptureActivityType DataCaptureActivityType { get; set; }
}
[Table("MasterDataCaptureActivities")]
public class MasterDataCaptureActivity : DataCaptureActivityBase
{
public virtual string SomeOtherField { get; set; }
}
Dans ce cas, les structures de tables seront ce
ExecuteNonQuery==========
CREATE TABLE [Activity] (
[Id] int not null identity(1,1)
, [ActivityType] int not null
, [Description] text null
);
ALTER TABLE [Activity] ADD CONSTRAINT [PK_Activity_2b28bd47] PRIMARY KEY ([Id])
ExecuteNonQuery==========
CREATE TABLE [DataCaptureActivities] (
[Id] int not null identity(1,1)
, [DataCaptureActivityType] int not null
, [Title] varchar(100) null
, [ActivityType] int not null
, [Description] text null
);
ALTER TABLE [DataCaptureActivities] ADD CONSTRAINT [PK_DataCaptureActivities_2b28bd47] PRIMARY KEY ([Id])
ExecuteNonQuery==========
CREATE TABLE [MasterDataCaptureActivities] (
[Id] int not null identity(1,1)
, [SomeOtherField] text null
, [Title] varchar(100) null
, [ActivityType] int not null
, [Description] text null
);
ALTER TABLE [MasterDataCaptureActivities] ADD CONSTRAINT [PK_MasterDataCaptureActivities_2b28bd47] PRIMARY KEY ([Id])
Mais dans ce cas, si vous voulez enum tous les ActivityBase
dont vous avez besoin de les rejoindre (Union
) sur le client.
Quels niveaux de la hiérarchie d'héritage mappez-vous à la base de données (en incluant les propriétés DbSet dans votre DbContext)? Parfois, il est logique de ne cartographier que les niveaux les plus bas dans la base de données. –
Comme David l'a dit, le DbContext est très important ici. Si vous exposez DbSet, le titre doit être sur DataCaptureActivityBase. –
bubi
@ DavidBrowne-Microsoft, @bubi Voir le schéma attendu, Le problème est que 'Title' est ajouté à la table' Activity' au lieu des deux tables dérivées – SJMan