简体   繁体   English

如何将基本表添加到使用Entity Framework创建TPH模型的现有实体?

[英]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: 我唯一想到的另一件事就是分阶段进行:

  1. Make BoatDesign inherit from CarDesign and Migrate (a discriminator column will be added to the existing table) 使BoatDesign继承自CarDesign和Migrate(将在现有表中添加一个鉴别CarDesign列)

  2. Add a new class CarDesign2 that also inherits from CarDesign (no database change required) 添加一个新类CarDesign2 ,该类也从CarDesign继承(无需更改数据库)

  3. Move the properties applicable only to CarDesign into CarDesign2 (no database change required) 将仅适用于CarDesign的属性移到CarDesign2 (无需更改数据库)

  4. 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将生成一个脚本,该脚本将移动数据以及拖放并重新创建)

  5. In the code change CarDesign to Design and CarDesign2 to CarDesign 在代码变化CarDesignDesignCarDesign2CarDesign

  6. 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(如果不是)。

  7. Let us know how you get on 让我们知道您的身体情况如何

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从Entity Framework中的现有表创建模型 - Creating model from existing table in Entity Framework 如何在实体框架6中混合使用TPH和TPT? - How can I mix TPH and TPT in Entity Framework 6? 如何在现有的远程数据库中添加表并将其链接到Entity Framework模型? - How to add table in existing remote database and link it to Entity Framework model? 实体框架TPH创建多个ID列 - Entity Framework TPH creating multiple ID columns Entity Framework 4 TPH:为什么无法获得鉴别器的价值? - Entity Framework 4 TPH: Why can't I get the value of the discriminator? 实体框架核心 TPH 与其他表中的鉴别器 - Entity Framework Core TPH with Discriminator in other table 使用TPH的Entity Framework的多级继承 - Multiple levels of inheritance with Entity Framework using TPH 如何将现有实体附加到通用的实体框架上下文中? - How can I attach an existing entity to the entity framework context in generic? 使用Entity Framework将模型映射到现有数据库表 - Map model to existing database table using Entity Framework 实体框架6模型第一:如何在基本实体已存在时添加继承实体 - Entity Framework 6 Model First: how to add inherited entity when base entity already exist
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM