在 Entity Framework 中的摘要 Class 上配置自动递增字段
Configuring an Auto Increment field on an Abstract Class in Entity Framework
我有一些类似于这些的代码优先实体:
public abstract class Animal {
public int ID { get; set; }
public int NumberOfLegs { get; set; }
}
public class Dog : Animal {
public string OtherDogRelatedStuff { get; set; }
}
public class Bird : Animal {
public string OtherBirdRelatedStuff { get; set; }
}
public class MyContext : DbContext {
public IDbSet<Animal> Animals { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
var pluraliser = PluralizationService.CreateService(new System.Globalization.CultureInfo("en-GB"));
modelBuilder.HasDefaultSchema("vs");
modelBuilder.Types().Configure(t => t.ToTable(pluraliser.Pluralize(t.ClrType.Name)));
// This next line doesn't give ID column IDENTITY(1,1)
modelBuilder.Entity<Animal>().Property(_ => _.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// This line puts IDENTITY(1,1) on Animal.ID, but causes errors when I try to add/update data.
//modelBuilder.Entity<Dog>().Property(_ => _.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
base.OnModelCreating(modelBuilder);
}
}
我想要每个类型 table...所以 table 看起来像这样:
CREATE TABLE Animals (
ID INT NOT NULL IDENTITY(1,1),
NumberOfLegs INT NOT NULL,
CONSTRAINT pkAnimals PRIMARY KEY (ID)
)
CREATE TABLE Dogs (
ID INT NOT NULL,
OtherDogRelatedStuff VARCHAR(200),
CONSTRAINT pkDogs PRIMARY KEY (ID),
CONSTRAINT fkAnimal_Dog FOREIGN KEY (ID) REFERENCES Animals(ID)
)
CREATE TABLE Birds (
ID INT NOT NULL,
OtherBirdRelatedStuff VARCHAR(200),
CONSTRAINT pkBirds PRIMARY KEY (ID),
CONSTRAINT fkAnimal_Bird FOREIGN KEY (ID) REFERENCES Animals(ID)
)
数据如下:
---Animals----------
ID NumberOfLegs
1 4
2 4
3 2
---Dogs---------------------
ID OtherDogRelatedStuff
1 Woof1
2 Woof2
---Birds---------------------
ID OtherCatRelatedStuff
3 Sqwark1
但我无法使自动递增 ID 工作或正确配置。
我试过这个:
modelBuilder.Entity<Animal>().Property(_ => _.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
但是因为 Animal
是抽象的,所以这似乎没有在 table.
上设置 IDENTITY(1,1)
属性
我也试过在 Dog
实体上做同样的事情,它正确地将身份 属性 添加到 Animals
table 中的 ID 列,但是当我尝试在 SaveChanges()
方法上向数据库添加新实体时,我得到一个 UpdateException
:
A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'ID'.
如何正确设置抽象类型上的ID列自动递增,并使其在添加数据时生效?
我会说使用接口或单独的抽象 class 来放置像这样的通用功能:
public interface Common{
int ID { get; set; }
}
public class Animal : Common {
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public int NumberOfLegs { get; set; }
}
public class Dog : Common {
public int ID { get; set; }
public string OtherDogRelatedStuff { get; set; }
}
有了这些模型...
public abstract class Animal
{
public int ID { get; set; }
public int NumberOfLegs { get; set; }
}
public class Dog : Animal
{
public string OtherDogRelatedStuff { get; set; }
}
public class Bird : Animal
{
public string OtherBirdRelatedStuff { get; set; }
}
...在上下文中...
public IDbSet<Animal> Animals { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Dog>().ToTable("Dogs");
modelBuilder.Entity<Bird>().ToTable("Birds");
}
...然后在包管理器中执行 Add-Migration "Animals"
然后 Update-Database -Script
你应该得到:
CREATE TABLE [dbo].[Animals] (
[ID] [int] NOT NULL IDENTITY,
[NumberOfLegs] [int] NOT NULL,
CONSTRAINT [PK_dbo.Animals] PRIMARY KEY ([ID])
)
CREATE TABLE [dbo].[Dogs] (
[ID] [int] NOT NULL,
[OtherDogRelatedStuff] [nvarchar](max),
CONSTRAINT [PK_dbo.Dogs] PRIMARY KEY ([ID])
)
CREATE INDEX [IX_ID] ON [dbo].[Dogs]([ID])
CREATE TABLE [dbo].[Birds] (
[ID] [int] NOT NULL,
[OtherBirdRelatedStuff] [nvarchar](max),
CONSTRAINT [PK_dbo.Birds] PRIMARY KEY ([ID])
)
CREATE INDEX [IX_ID] ON [dbo].[Birds]([ID])
ALTER TABLE [dbo].[Dogs]
ADD CONSTRAINT [FK_dbo.Dogs_dbo.Animals_ID] FOREIGN KEY ([ID])
REFERENCES [dbo].[Animals] ([ID])
ALTER TABLE [dbo].[Birds]
ADD CONSTRAINT [FK_dbo.Birds_dbo.Animals_ID] FOREIGN KEY ([ID])
REFERENCES [dbo].[Animals] ([ID])
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'etc)
这是你想要的,对吧?
参考:
Inheritance with EF Code First: Part 2 – Table per Type (TPT)
请注意,如果字段最初是在没有身份的情况下创建的(反之亦然),有时您可能 运行 会遇到使用身份创建的字段的问题。您可以通过删除并重新创建 table 来解决此问题:
我遇到了同样的问题,我使用摘要中的数据注释修复了它 class,如下所示:
public abstract class Animal {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public int NumberOfLegs { get; set; }
}
我有一些类似于这些的代码优先实体:
public abstract class Animal {
public int ID { get; set; }
public int NumberOfLegs { get; set; }
}
public class Dog : Animal {
public string OtherDogRelatedStuff { get; set; }
}
public class Bird : Animal {
public string OtherBirdRelatedStuff { get; set; }
}
public class MyContext : DbContext {
public IDbSet<Animal> Animals { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
var pluraliser = PluralizationService.CreateService(new System.Globalization.CultureInfo("en-GB"));
modelBuilder.HasDefaultSchema("vs");
modelBuilder.Types().Configure(t => t.ToTable(pluraliser.Pluralize(t.ClrType.Name)));
// This next line doesn't give ID column IDENTITY(1,1)
modelBuilder.Entity<Animal>().Property(_ => _.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// This line puts IDENTITY(1,1) on Animal.ID, but causes errors when I try to add/update data.
//modelBuilder.Entity<Dog>().Property(_ => _.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
base.OnModelCreating(modelBuilder);
}
}
我想要每个类型 table...所以 table 看起来像这样:
CREATE TABLE Animals (
ID INT NOT NULL IDENTITY(1,1),
NumberOfLegs INT NOT NULL,
CONSTRAINT pkAnimals PRIMARY KEY (ID)
)
CREATE TABLE Dogs (
ID INT NOT NULL,
OtherDogRelatedStuff VARCHAR(200),
CONSTRAINT pkDogs PRIMARY KEY (ID),
CONSTRAINT fkAnimal_Dog FOREIGN KEY (ID) REFERENCES Animals(ID)
)
CREATE TABLE Birds (
ID INT NOT NULL,
OtherBirdRelatedStuff VARCHAR(200),
CONSTRAINT pkBirds PRIMARY KEY (ID),
CONSTRAINT fkAnimal_Bird FOREIGN KEY (ID) REFERENCES Animals(ID)
)
数据如下:
---Animals----------
ID NumberOfLegs
1 4
2 4
3 2
---Dogs---------------------
ID OtherDogRelatedStuff
1 Woof1
2 Woof2
---Birds---------------------
ID OtherCatRelatedStuff
3 Sqwark1
但我无法使自动递增 ID 工作或正确配置。
我试过这个:
modelBuilder.Entity<Animal>().Property(_ => _.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
但是因为 Animal
是抽象的,所以这似乎没有在 table.
IDENTITY(1,1)
属性
我也试过在 Dog
实体上做同样的事情,它正确地将身份 属性 添加到 Animals
table 中的 ID 列,但是当我尝试在 SaveChanges()
方法上向数据库添加新实体时,我得到一个 UpdateException
:
A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'ID'.
如何正确设置抽象类型上的ID列自动递增,并使其在添加数据时生效?
我会说使用接口或单独的抽象 class 来放置像这样的通用功能:
public interface Common{
int ID { get; set; }
}
public class Animal : Common {
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public int NumberOfLegs { get; set; }
}
public class Dog : Common {
public int ID { get; set; }
public string OtherDogRelatedStuff { get; set; }
}
有了这些模型...
public abstract class Animal
{
public int ID { get; set; }
public int NumberOfLegs { get; set; }
}
public class Dog : Animal
{
public string OtherDogRelatedStuff { get; set; }
}
public class Bird : Animal
{
public string OtherBirdRelatedStuff { get; set; }
}
...在上下文中...
public IDbSet<Animal> Animals { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Dog>().ToTable("Dogs");
modelBuilder.Entity<Bird>().ToTable("Birds");
}
...然后在包管理器中执行 Add-Migration "Animals"
然后 Update-Database -Script
你应该得到:
CREATE TABLE [dbo].[Animals] (
[ID] [int] NOT NULL IDENTITY,
[NumberOfLegs] [int] NOT NULL,
CONSTRAINT [PK_dbo.Animals] PRIMARY KEY ([ID])
)
CREATE TABLE [dbo].[Dogs] (
[ID] [int] NOT NULL,
[OtherDogRelatedStuff] [nvarchar](max),
CONSTRAINT [PK_dbo.Dogs] PRIMARY KEY ([ID])
)
CREATE INDEX [IX_ID] ON [dbo].[Dogs]([ID])
CREATE TABLE [dbo].[Birds] (
[ID] [int] NOT NULL,
[OtherBirdRelatedStuff] [nvarchar](max),
CONSTRAINT [PK_dbo.Birds] PRIMARY KEY ([ID])
)
CREATE INDEX [IX_ID] ON [dbo].[Birds]([ID])
ALTER TABLE [dbo].[Dogs]
ADD CONSTRAINT [FK_dbo.Dogs_dbo.Animals_ID] FOREIGN KEY ([ID])
REFERENCES [dbo].[Animals] ([ID])
ALTER TABLE [dbo].[Birds]
ADD CONSTRAINT [FK_dbo.Birds_dbo.Animals_ID] FOREIGN KEY ([ID])
REFERENCES [dbo].[Animals] ([ID])
INSERT [dbo].[__MigrationHistory]([MigrationId], [ContextKey], [Model], [ProductVersion])
VALUES (N'etc)
这是你想要的,对吧?
参考: Inheritance with EF Code First: Part 2 – Table per Type (TPT)
请注意,如果字段最初是在没有身份的情况下创建的(反之亦然),有时您可能 运行 会遇到使用身份创建的字段的问题。您可以通过删除并重新创建 table 来解决此问题:
我遇到了同样的问题,我使用摘要中的数据注释修复了它 class,如下所示:
public abstract class Animal {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public int NumberOfLegs { get; set; }
}