[英]EF Code first one way navigation property
I have the following entities: 我有以下实体:
[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; }
}
I have no fluent configurations on the DbContext
我在
DbContext
上没有流畅的配置
So the model exists of Scripts which must be bound to an application. 因此,存在必须绑定到应用程序的脚本模型。 Applications can have a startScript defined.
应用程序可以定义一个startScript。 All this I already have working.
这一切我已经在工作了。
Now I am in need of a navigation property: Application.StartScript
. 现在,我需要一个导航属性:
Application.StartScript
。
The question is how can I add the navigation property on Application
without having to add a the equivalent navigation property on Script
. 问题是,如何在
Application
上添加导航属性, 而不必在Script
上添加等效的导航属性。
Thanks in advance! 提前致谢!
EDIT: When I run Add-Migration the following migration code is generated: 编辑:当我运行添加迁移时,将生成以下迁移代码:
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");
}
This creates a new column on Scripts which I don't need, as I already have the StartScriptID column. 这将在不需要的脚本上创建一个新列,因为我已经有了StartScriptID列。
EDIT: Update after @haim770 answer 编辑:@ 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");
}
It doesn't understand that it should use the already existing StartScriptID. 它不了解它应该使用已经存在的StartScriptID。 Is there a way to point it in the right direction?
有没有办法将其指向正确的方向?
EDIT: Wanted database structure: 编辑:想要的数据库结构:
Applications: 应用范围:
Scripts: 脚本:
EDIT: 编辑:
public class Application
{
[InverseProperty("StartScript")]
public long? StartScriptID { get; set; }
[ForeignKey("StartScriptID")]
public virtual Script StartScript { get; set; }
}
I was thinking there was no changes needed in the database, so I have tried adding migration with -IgnoreChanges. 我以为数据库中不需要更改,因此我尝试使用-IgnoreChanges添加迁移。 But then I got an
EntityCommandExecutionException
when querying for entities: "Invalid column name 'Application_ID'". 但是然后在查询实体时出现了
EntityCommandExecutionException
:“无效的列名'Application_ID'”。 So the Entity Framework needs some configuration for telling to use the StartScriptID
property. 因此,实体框架需要一些配置以告知使用
StartScriptID
属性。
You can modify the mapping using the ForeignKeyAttribute and the InversePropertyAttribute . 您可以使用ForeignKeyAttribute和InversePropertyAttribute修改映射。 If that doesn't work the way you want, you can always edit the migration yourself before applying it.
如果那不能按照您想要的方式工作,则始终可以在应用迁移之前自行编辑迁移。
If you want to customize the column name, try the ColumnAttribute: 如果要自定义列名称,请尝试使用ColumnAttribute:
public class Application
{
[Column("DatabaseColumnName")]
public long? StartScriptID { get; set; }
[ForeignKey("StartScriptID")]
public virtual Script StartScript { get; set; }
}
A longer explanation can be found here: http://msdn.microsoft.com/de-de/data/gg193958.aspx 可以在这里找到更长的说明: http : //msdn.microsoft.com/de-de/data/gg193958.aspx
Try to use EntityTypeConfiguration It makes more easy to handle this kind of problem. 尝试使用EntityTypeConfiguration可以更轻松地处理此类问题。 Then:
然后:
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);
}
}
Don't forget to tell EF about the Mappings: (Call it inside OnModelCreating ) 不要忘了告诉EF有关映射的信息:(在OnModelCreating内部调用它)
public static class MappingConfig
{
public static void ConfigureMap(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ApplicationMap());
modelBuilder.Configurations.Add(new ScriptMap());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.