我的数据库中有一个名为CarDesign的现有表,它与Project具有一对一的关系。我想添加一个名为Design的基表,以便在TPH表中使用。那么我可以为BoatDesign这样的东西添加鉴别器。问题是实体框架想要删除旧表并创建一个新表。如何保留我的数据并使用鉴别器来表示当前记录?
我正在使用带有SQL的实体框架5。我也将更新到实体框架6,如果这有助于解决问题。项目是带有c#
的asp.net MVC4Mapping
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);
}
}
模型
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; }
}
}
所以我希望有
公共类CarDesign:设计
{
}
答案 0 :(得分:0)
由于您希望采用TPH继承,因此EF必须为基类Design
创建一个表,从而删除旧的CarDesign表。您可以尝试使用迁移来避免丢失数据,但我从未尝试使用现有数据实现TPH,因此我无法保证迁移适用于它(我担心它可能不会)。
至于鉴别器,EF已经为你处理了这个问题。
这些类看起来像这样:
public abstract class Design
{
Public int Id { get; set; }
...
}
public class CarDesign : Design
{
...
}
public class BoatDesign : Design
{
...
}
然后,您可以选择为设计创建单个DbSet,也可以为每个子类型创建一个DbSet。你在这里的选择:
public DbSet<Design> Designs { get; set; }
或:
public DbSet<CarDesign> CarDesigns { get; set; }
public DbSet<BoatDesign> BoatDesigns { get; set; }
或者你可以拥有所有三个DbSet。
如果你想要查询设计DbSet并让它只返回CarDesigns,你可以这样做:
var finishedCarDesigns = context.Designs.OfType<CarDesign>().Where(cd => cd.Finished = true);
答案 1 :(得分:0)
如果您从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; }
}
然后添加了基类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;
}
您可以将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");
}
如果要修复外键,sql会变得更复杂。我能想到的另一件事就是分阶段进行:
让BoatDesign
继承自CarDesign
和迁移(将鉴别器列添加到现有表中)
添加一个同样继承自CarDesign2
的新类CarDesign
(无需更改数据库)
将仅适用于CarDesign
的属性移至CarDesign2
(无需更改数据库)
在CarDesigns to Designs的数据库中编写表名更改(Sql Server将生成一个脚本,该脚本将移动数据以及删除并重新创建)
在代码更改CarDesign
至Design
和CarDesign2
至CarDesign
查看步骤5创建的迁移。如果它正在删除并重新创建CarDesign
表,则将其替换为步骤4中生成的sql,如果它不是woo-hoo!
告诉我们您的情况