Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在引用模型中添加外键而不向主体模型添加导航属性_C#_Sql Server_Entity Framework_Entity Framework 6_Ef Code First - Fatal编程技术网

C# 如何在引用模型中添加外键而不向主体模型添加导航属性

C# 如何在引用模型中添加外键而不向主体模型添加导航属性,c#,sql-server,entity-framework,entity-framework-6,ef-code-first,C#,Sql Server,Entity Framework,Entity Framework 6,Ef Code First,我在父模型和子模型之间有一对多关系。按照项目的约定,我需要创建一个单独的类来映射从EntityTypeConfiguration类扩展的每个实体 public class Parent { public int Id { get; set; } [Required] public string ParentName { get; set; } //public IEnumerable<Child> Children { get; set; } } p

我在父模型和子模型之间有一对多关系。按照项目的约定,我需要创建一个单独的类来映射从EntityTypeConfiguration类扩展的每个实体

public class Parent
{
    public int Id { get; set; }
    [Required]
    public string ParentName { get; set; }
    //public IEnumerable<Child> Children { get; set; }
}

public class Child
{
    [Key]
    public int ChildId { get;  set; }

    [Required]
    public string ChildName { get; set; }

    [ForeignKey]
    public int CustomParentId { get; set; }

    public Parent Parent { get; set; }
}

public class ChildMap : EntityTypeConfiguration<Child>
{

}

如何在ChildMap中添加外键而不向父模型添加子导航属性?

为了清晰起见,将我的注释扩展为答案。子记录可以包含对其父记录的引用,而无需父集合,并且可以使用或不使用子记录中指定的父ID字段来完成:

public class ParentMap : EntityTypeConfiguration<Parent>
{
  ToTable("Parents");
  HasKey(x => x.Id)
    .Property(x => x.Id)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}

//With Parent ID in Child:
public class ChildMap : EntityTypeConfiguration<Child>
{
  ToTable("Children");
  HasKey(x => x.ChildId)
    .Property(x => x.ChildId)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

  HasRequired(x => x.Parent)
    .WithMany()
    .HasForeignKey(x => CustomParentId);
}

// Without Parent ID in child. (Column in table called "CustomParentId")
public class ChildMap : EntityTypeConfiguration<Child>
{
  ToTable("Children");
  HasKey(x => x.ChildId)
    .Property(x => x.ChildId)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

  HasRequired(x => x.Parent)
    .WithMany()
    .Map(x => x.MapKey("CustomParentId"));
}
如果使用以下代码加载子项

var child = myContext.Children
  .SingleOrDefault(x => x.ChildId == 1);
然后使用…访问父级

string parentName = child.Parent?.Name;
如果没有虚拟父级,则未加载父级引用,因此父级将为null。如果父级是虚拟的,那么将进行延迟加载调用来检索父级,您将获得关联的实体。延迟加载通常是有帮助的,但不是很有效,因为它可能导致数据库的第二次往返。在这两种情况下,如果您:

var child = myContext.Children
  .Include(x => x.Parent)
  .SingleOrdefault(x => x.ChildId == 1);
然后父引用将被加载并可访问,虚拟或否

或者,检索数据的更好方法是使用单独的视图模型,并从数据和相关数据中选择所需的字段。例如,使用返回带有父ID和名称的子详细信息的viewmodel:

var child = myContext.Children
  .Select(x => new ChildSummaryViewModel 
  {
    ChildId = x.ChildId,
    Name = x.Name,
    ParentId = x.Parent.Id,
    ParentName = x.Parent.Name
  })
  .SingleOrdefault(x => x.ChildId == 1);
这不需要父级上的.Include,并将从相关父级加载详细信息。在有一个相关实体的情况下,这似乎不太实际,但在处理有许多相关实体的大型实体的情况下,这可以大大减少查询时间和触发额外延迟加载查询的风险,并减少从数据库发回的数据的大小。而不是整个实体,只是您关心的属性


更新实体时,您应该使用。包括相关实体以进行调整或更改关系。

HasRequiredx=>x.Parent.WithMany.HasForeignKeyx=>x.CustomParentId必须定义为父级上的[Key]才能工作。通过使用.Mapx=>x.MapKeyCustomParentId而不是.ForeignKey/w EF 6,或者我相信,您可以在没有在子级中定义FK的情况下执行此操作。ForeignKeyCustomParentId现在与EF Core一起工作,以建立没有显式属性的外键。我遵循了您的建议,但父导航属性从DB中为空,当数据库中的子行和父行之间存在关系值时仍然如此。
var child = myContext.Children
  .Select(x => new ChildSummaryViewModel 
  {
    ChildId = x.ChildId,
    Name = x.Name,
    ParentId = x.Parent.Id,
    ParentName = x.Parent.Name
  })
  .SingleOrdefault(x => x.ChildId == 1);