EF Code第一个单向导航属性

时间:2014-12-02 08:26:27

标签: c# entity-framework ef-migrations

我有以下实体:

[KnownType(typeof(Script))]
public class Application : IEntity
{
    public long ID { get; set; }
    public string Name { get; set; }
    public long? StartScriptID { get; set; }
    // Other properties...

    // Navigation properties:
    public virtual Script StartScript { get; set; }   // new
    public virtual List<Script> Scripts { get; set; }
}

[KnownType(typeof(Application))]
public class Script : IEntity
{
    public long ID { get; set; }
    public string Name { get; set; }
    // Other properties...

    // Navigation properties:
    public virtual Application Application { get; set; }
}

我在DbContext

上没有流畅的配置

因此模型存在必须绑定到应用程序的脚本。应用程序可以定义startScript。所有这些我已经有了工作。

现在我需要一个导航属性:Application.StartScript

问题是如何在Application 上添加导航属性,而必须在Script上添加等效的导航属性。

提前致谢!



编辑:当我运行Add-Migration时,会生成以下迁移代码:

public override void Up()
{
    DropForeignKey("dbo.Scripts", "ApplicationID", "dbo.Applications");
    AddColumn("dbo.Scripts", "Application_ID", c => c.Long());
    CreateIndex("dbo.Applications", "StartScriptID");
    CreateIndex("dbo.Scripts", "Application_ID");
    AddForeignKey("dbo.Applications", "StartScriptID", "dbo.Scripts", "ID");
    AddForeignKey("dbo.Scripts", "Application_ID", "dbo.Applications", "ID");
}

这会在Scripts上创建一个我不需要的新列,因为我已经有了StartScriptID列。


编辑:@ haim770回答后更新

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Application>().HasOptional(x => x.StartScript).WithOptionalDependent(x => x.Application);
}

public override void Up()
{
    DropForeignKey("dbo.Scripts", "ApplicationID", "dbo.Applications");
    DropIndex("dbo.Scripts", new[] { "ApplicationID" });
    RenameColumn(table: "dbo.Applications", name: "ApplicationID", newName: "StartScript_ID");
    AddColumn("dbo.Scripts", "Application_ID", c => c.Long());
    CreateIndex("dbo.Applications", "StartScript_ID");
    CreateIndex("dbo.Scripts", "Application_ID");
    AddForeignKey("dbo.Scripts", "Application_ID", "dbo.Applications", "ID");
    AddForeignKey("dbo.Applications", "StartScript_ID", "dbo.Scripts", "ID");
}

它不明白它应该使用已经存在的StartScriptID。有没有办法将它指向正确的方向?


编辑:通缉数据库结构:

应用:

  • ID,PK,bigint,not null
  • 名称,nvarchar(最大),非空
  • StartScriptID,bigint,null

脚本:

  • ID,PK,bigint,not null
  • 名称,nvarchar(最大),非空
  • ApplicationID,FK,bigint,not null


编辑:

public class Application
{
    [InverseProperty("StartScript")]
    public long? StartScriptID { get; set; }
    [ForeignKey("StartScriptID")]
    public virtual Script StartScript { get; set; }
}

我当时认为数据库中没有需要进行任何更改,因此我尝试使用-IgnoreChanges添加迁移。但是在查询实体时我得到EntityCommandExecutionException:“无效的列名'Application_ID'”。因此,实体框架需要一些配置来告知使用StartScriptID属性。

2 个答案:

答案 0 :(得分:0)

您可以使用ForeignKeyAttributeInversePropertyAttribute修改映射。 如果这不符合您的要求,您可以在应用之前自行编辑迁移。

如果要自定义列名,请尝试使用ColumnAttribute:

public class Application
{
    [Column("DatabaseColumnName")]
    public long? StartScriptID { get; set; }
    [ForeignKey("StartScriptID")]
    public virtual Script StartScript { get; set; }
}

可以在此处找到更长的解释:http://msdn.microsoft.com/de-de/data/gg193958.aspx

答案 1 :(得分:0)

尝试使用EntityTypeConfiguration这样可以更轻松地处理此类问题。然后:

public class Application 
{
    public long ID { get; set; }
    public string Name { get; set; }
    public long? StartScriptID { get; set; }
    // Other properties...

    // Navigation properties:
    public virtual Script StartScript { get; set; }   // new
    public virtual ICollection<Script> Scripts { get; set; }
}

public class Script 
{
    public long ID { get; set; }
    public string Name { get; set; }
    public int ApplicationId { get; set; }
    // Other properties...

    // Navigation properties:
    public virtual Application Application { get; set; }
}

public class ApplicationMap : EntityTypeConfiguration<Application>
{
    public ApplicationMap()
    {
        this.HasKey(t => t.ID);

        this.ToTable("TB_APLICATION", "aplication");

        this.Property(t => t.ID).HasColumnName("id");
        this.Property(t => t.Name).HasColumnName("name");
        this.Property(t => t.StartScriptID).HasColumnName("startscript_id");

        this.HasOptional(t => t.StartScript)
            .WithMany()
            .HasForeignKey(t => t.StartScriptID);
    }
}

public class ScriptMap : EntityTypeConfiguration<Script>
{
    public ScriptMap()
    {
        this.HasKey(t => t.ID);

        this.ToTable("TB_APLICATION", "aplication");

        this.Property(t => t.ID).HasColumnName("id");
        this.Property(t => t.Name).HasColumnName("name");

        this.HasRequired(t => t.Application)
            .WithMany(w => w.Scripts)
            .HasForeignKey(t => t.ApplicationId);
    }
}

别忘了告诉EF关于映射:(在里面调用 OnModelCreating

public static class MappingConfig
{
     public static void ConfigureMap(DbModelBuilder modelBuilder)
     {
         modelBuilder.Configurations.Add(new ApplicationMap());
         modelBuilder.Configurations.Add(new ScriptMap());
     }
 }