[英]How can I add a base table to an existing entity creating TPH model using Entity Framework?
I have an existing table in my database called CarDesign that has a one to one relationship with Project. 我的数据库中有一个名为CarDesign的现有表,该表与Project具有一对一关系。 I want to add a base table called Design to use in a TPH table. 我想添加一个称为Design的基本表以在TPH表中使用。 So then I can add discriminators for things like BoatDesign. 因此,我可以为BoatDesign等添加区分符。 The problem is entity framework wants to just drop the old table and make a new one. 问题是实体框架只想删除旧表并创建一个新表。 How can I keep my data and have a discriminator to represent the current records? 如何保存我的数据并有一个鉴别符来代表当前记录?
I'm using entity framework 5 with SQL. 我正在使用带有SQL的实体框架5。 I am also going to update to entity framework 6 if that helps the issue. 如果有帮助的话,我还将更新到实体框架6。 Project is asp.net MVC4 with c# 项目是带有C#的ASP.NET MVC4
Mapping
public class CarDesignMap : EntityTypeConfiguration<CarDesign>
{
public CarDesignMap()
{
// Primary Key
this.HasKey(t => t.Id);
// Properties
//this.Property(t => t.Name)
//.IsRequired();
this.Property(t => t.RowVersion)
.IsRequired()
.IsFixedLength()
.HasMaxLength(8)
.IsRowVersion();
// Relationships
this.HasMany(t => t.InputVoltages)
.WithMany(t => t.CarDesign)
.Map(m =>
{
m.ToTable("InputVoltageCarDesign");
m.MapLeftKey("CarDesign_Id");
m.MapRightKey("InputVoltage_Id");
});
this.HasMany(t => t.LensColors)
.WithMany(t => t.CarDesign)
.Map(m =>
{
m.ToTable("LensCarDesign");
m.MapLeftKey("CarDesign_Id");
m.MapRightKey("LensColor_Id");
});
this.HasMany(t => t.LightSourceColors)
.WithMany(t => t.CarDesign)
.Map(m =>
{
m.ToTable("LightSourceColorCarDesign");
m.MapLeftKey("CarDesign_Id");
m.MapRightKey("LightSourceColor_Id");
});
this.HasMany(t => t.Standards)
.WithMany(t => t.CarDesign)
.Map(m =>
{
m.ToTable("StandardCarDesign");
m.MapLeftKey("CarDesign_Id");
m.MapRightKey("Standard_Id");
});
this.HasOptional(t => t.LightSource)
.WithMany(t => t.CarDesign)
.HasForeignKey(d => d.LightSourceId);
}
}
model 模型
public class CarDesign
{
public CarDesign()
{
Approvals = new List<Approval>();
Standards = new List<Standard>();
Connectors = new List<Connector>();
InputVoltages = new List<InputVoltage>();
LensColors = new List<LensColor>();
LightSourceColors = new List<LightSourceColor>();
}
[Required]
[Display(Name = "Product Name")]
public string Name { get; set; }
public PdsStatus Status { get; set; }
public Guid SubmittedById { get; set; }
[Display(Name = "Submitted By")]
public virtual User SubmittedBy { get; set; }
public Guid? ApprovedById { get; set; }
[Display(Name = "Approved By")]
public virtual User ApprovedBy { get; set; }
[Display(Name = "Approval Date")]
[DataType(DataType.Date)]
public DateTime? ApprovalDate { get; set; }
[Display(Name = "Submit Date")]
[DataType(DataType.Date)]
public DateTime SubmittalDate { get; set; }
public string SubmittalDateDisplay
{
get
{
return (SubmittalDate == null) ? "Not Set" : ((DateTime)SubmittalDate).ToString("MM/dd/yy");
}
}
public string Description { get; set; }
[Display(Name = "Market and Uses")]
public string MarketAndUses{get;set;}
[Display(Name = "Target M & L")]
[DataType(DataType.Currency)]
public double? TargetPrice { get; set; }
[Display(Name = "Annual Qty")]
public int? AnnualQuantities { get; set; }
[Display(Name = "Current Draw")]
public double? CurrentDraw { get; set; }
[Display(Name = "Light Source")]
public int? LightSourceId { get; set; }
public virtual LightSource LightSource { get; set; }
public LengthUnitOfMeasure LengthUnitOfMeasure { get; set; }
public WeightUnitOfMeasure WeightUnitOfMeasure { get; set; }
public PhotometricIntensityUnitOfMeasure LightIntensityUnitOfMeasure{ get; set; }
public virtual ICollection<Approval> Approvals { get; set; }
public virtual ICollection<Standard> Standards { get; set; }
public virtual ICollection<Connector> Connectors { get; set; }
public virtual ICollection<InputVoltage> InputVoltages { get; set; }
public virtual ICollection<LensColor> LensColors { get; set; }
public virtual ICollection<LightSourceColor> LightSourceColors { get; set; }
}
}
so I would desire to have 所以我希望有
public class CarDesign : Design 公共类CarDesign:设计
{ {
} }
Since you want to adopt TPH inheritance, EF will have to create a table for the base class Design
, thus droping your old CarDesign table. 由于您想采用TPH继承,因此EF必须为基类Design
创建一个表,从而删除旧的CarDesign表。 You can try to use migrations to avoid losing data but I've never tried to implement TPH with existing data so I cannot garantee that migrations will work for it (I'm afraid it probably won't). 您可以尝试使用迁移来避免丢失数据,但我从未尝试使用现有数据来实现TPH,因此我无法保证迁移将对其起作用(恐怕可能不会)。
As for the discriminator, EF already handles this for you. 至于区分符,EF已经为您处理了。
The classes would look like this: 这些类如下所示:
public abstract class Design
{
Public int Id { get; set; }
...
}
public class CarDesign : Design
{
...
}
public class BoatDesign : Design
{
...
}
And then, you can choose to create a single DbSet for Design or you can create one DbSet for each subtype. 然后,您可以选择为Design创建一个DbSet,也可以为每个子类型创建一个DbSet。 Your choice here: 您在这里的选择:
public DbSet<Design> Designs { get; set; }
or: 要么:
public DbSet<CarDesign> CarDesigns { get; set; }
public DbSet<BoatDesign> BoatDesigns { get; set; }
Or you can have all three DbSets. 或者,您可以拥有所有三个DbSet。
In case you want query Designs DbSet and have it return only CarDesigns, you can do it like this: 如果要查询Designs DbSet并使其仅返回CarDesigns,则可以这样进行:
var finishedCarDesigns = context.Designs.OfType<CarDesign>().Where(cd => cd.Finished = true);
Also, you may find this link useful: http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx 另外,您可能会发现此链接有用: http : //weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1 -表-每个层次结构tph.aspx
If you started with Foo
: 如果您从Foo
开始:
public class Foo
{
public int ID { get; set; }
public string Name { get; set; }
public int BarID { get; set; }
public virtual Bar Bar { get; set; }
}
Then added a base class Baz
然后添加一个基类Baz
public class Foo : Baz
{
public string Name { get; set; }
public int BarID { get; set; }
public virtual Bar Bar { get; set; }
}
public class Baz
{
public int ID { get; set; }
public int ApprovedBy { get; set;
}
You could add your sql to the migration like this: 您可以像这样将sql添加到迁移中:
public override void Up()
{
DropForeignKey("dbo.Foos", "BarID", "dbo.Bars");
DropIndex("dbo.Foos", new[] { "BarID" });
CreateTable(
"dbo.Bazs",
c => new
{
ID = c.Int(nullable: false, identity: true),
ApprovedBy = c.Int(nullable: false),
Name = c.String(),
BarID = c.Int(),
Discriminator = c.String(nullable: false, maxLength: 128),
})
.PrimaryKey(t => t.ID)
.ForeignKey("dbo.Bars", t => t.BarID)
.Index(t => t.BarID);
//Put your sql here to run before the table is dropped
Sql(@"INSERT INTO dbo.Bazs (Name, BarID, Discriminator)
SELECT Name, BarID, 'Foo' FROM dbo.Foos");
DropTable("dbo.Foos");
}
The sql gets more complicated if you have foreign keys to fix up. 如果您要修复外键,则sql会变得更加复杂。 The only other thing I can think of is to go in stages: 我唯一想到的另一件事就是分阶段进行:
Make BoatDesign
inherit from CarDesign
and Migrate (a discriminator column will be added to the existing table) 使BoatDesign
继承自CarDesign
和Migrate(将在现有表中添加一个鉴别CarDesign
列)
Add a new class CarDesign2
that also inherits from CarDesign
(no database change required) 添加一个新类CarDesign2
,该类也从CarDesign
继承(无需更改数据库)
Move the properties applicable only to CarDesign
into CarDesign2
(no database change required) 将仅适用于CarDesign
的属性移到CarDesign2
(无需更改数据库)
Script a table name change in the database for CarDesigns to Designs (Sql Server will generate a script that will move the data as well as drop and re-create) 在数据库中编写表名更改的脚本,以实现从CarDesigns到Designs的更改(Sql Server将生成一个脚本,该脚本将移动数据以及拖放并重新创建)
In the code change CarDesign
to Design
and CarDesign2
to CarDesign
在代码变化CarDesign
来Design
和CarDesign2
到CarDesign
Look at the migration created by step 5. If it is dropping and recreating the CarDesign
table then replace it with the sql generated in step 4, If it isn't woo-hoo! 查看由步骤5创建的迁移。如果正在删除并重新创建CarDesign
表,则将其替换为在步骤4中生成的sql(如果不是)。
Let us know how you get on 让我们知道您的身体情况如何
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.