【问题标题】:EntityFramework - One to many relationshipEntityFramework - 一对多关系
【发布时间】:2017-04-04 05:35:58
【问题描述】:

我在 MapHeader 和 MapDetail 表之间存在一对多的关系 因此,一个地图头可以有多个地图细节。 在数据库中,MapDetail表有外键MapHeaderID,映射到MapHeader表中的pk(MapHeaderId)。

我在 EntityFramework Code-first 中定义如下:

public class MapHeader
{
    public int MapHeaderID { get; set; }
    ....
    public virtual ICollection<MapDetail> mapDetails
    {
        get;
        set;
    } 
 }

public class MapDetail
{
    public int MapDetailID { get; set; }
    public int MapHeaderID { get; set; }
    ....
    public virtual MapHeader mapheader { get; set; }
}

FLUNETAPI

modelBuilder.Entity<MapDetail>()
            .HasRequired<MapHeader>(md => md.mapheader)
            .WithMany(mh => mh.mapDetails)
            .HasForeignKey(md => md.MapHeaderID);

它没有链接!我在 mapdetail 记录/对象中的 mapheader 属性仍然为空...我做错了什么?

代码 - 以剃刀视图编写

foreach (MapDetail geMapDetail in Model.mapDetails)
   {
     if(...)
     {
       if(...){...}
       else{
          <td>
          foreach(..)
          {
              var term = geMapDetail.Term == 0 ? geMapDetail.mapheader.Term : geMapDetail.Term;
          }
          </td>
       }
     }

由于 mapheader 为空,上述 geMapDetail.mapheader 上的代码崩溃

我的查询在存储过程中

select distinct md.yearid, md.assessmentid, md.resulttypeid,
    concat(ah.name, ' - ', a.name) as Name, md.term, md.semester, md.month, md.week,
   md.MapDetailID, md.MapHeaderID, md.ColourFormatType, md.ResultTypeIDs,
    md.RowOrder, md.Attendance, md.EffectSize, md.Growth, md.IndicatorID,
    md.TeacherNameRequired, md.AllowEdit, md.PageHeaderID, md.IncludePreviousTerms,
    md.IncludePreviousSemesters, y.year
from mapdetail md
left outer join assessments a on a.assessmentid = md.assessmentid
left outer join assessments ah on ah.assessmentID = a.headerID
left outer join years y on md.yearID = y.yearID
left outer join assessmentresulttypes art on a.assessmentid = art.assessmentid
left outer join resulttypes rt on rt.resulttypeid = art.resulttypeid
where  md.mapheaderid = 22;

DBCONTEXT

 public MapDetailResultSet Find_MapDetails(int mapHeaderId, int yearId, string classIds, int indicatorGroup, string indicatorIds)
    {
        var query = "CALL Find_MapDetails(@mapHeaderId, @yearId, @classIds, @indicatorGroup, @indicatorIds)";

        MySqlParameter[] mySqlParams = new MySqlParameter[] { new MySqlParameter("mapHeaderId", mapHeaderId),
                                                                new MySqlParameter("yearId", yearId),
                                                                new MySqlParameter("classIds", classIds),
                                                                new MySqlParameter("indicatorGroup", indicatorGroup),
                                                                new MySqlParameter("indicatorIds", indicatorIds)
                                                            };

        MapDetailResultSet mapdetails = new MapDetailResultSet();

        using (var multiResultSet = DbContextExtensions.MultiResultSetSqlQuery(this, query, mySqlParams))
        {
            mapdetails.mapDetails = multiResultSet.ResultSetFor<MapDetail>().ToList();
            //other result sets
            ...

        }
  return mapdetails;
  }

我还在 DBContext 中禁用了延迟加载:(没有帮助)

 public geContext(string connString):base(connString) 
    {
        this.Configuration.LazyLoadingEnabled = false;
        Database.SetInitializer(new MySqlInitializer());
    }

更新

select distinct md.yearid, md.assessmentid, md.resulttypeid,
    concat(ah.name, ' - ', a.name) as Name, md.term, md.semester, md.month, md.week,
   md.MapDetailID, md.MapHeaderID, md.ColourFormatType, md.ResultTypeIDs,
    md.RowOrder, md.Attendance, md.EffectSize, md.Growth, md.IndicatorID,
    md.TeacherNameRequired, md.AllowEdit, md.PageHeaderID, 
    md.IncludePreviousTerms,
    md.IncludePreviousSemesters, y.year
   from mapdetail md
   left outer join assessments a on a.assessmentid = md.assessmentid
   left outer join assessments ah on ah.assessmentID = a.headerID
   left outer join years y on md.yearID = y.yearID
   left outer join assessmentresulttypes art on a.assessmentid = art.assessmentid
   left outer join resulttypes rt on rt.resulttypeid = art.resulttypeid
   left outer join mapheader mh on mh.mapheaderID = md.mapheaderID
    where  md.mapheaderid = 22;

【问题讨论】:

  • 您是否允许在 MapDetail 表中为 null ?
  • no my mapheaderid in mapdetail 的值为 22,可以在 mapheader 表中找到
  • 我正在使用存储过程来加载 mapdetail 这应该不是我确定的问题
  • 所以表在数据库中设置正确并且有实际数据。但是当您查询MapDetail 时,mapheader 属性是null。正确的?在这种情况下,我假设您正在使用延迟加载,并且您必须告诉 EF 也实际加载 MapHeader。你能展示你用来查询数据的代码吗?
  • 确定让我更新我的帖子

标签: entity-framework one-to-many ef-fluent-api


【解决方案1】:

仅使用您的模型类对我来说效果很好。您甚至不需要 FluentAPI 代码,因为您的类定义遵循 Code-First 外键约定。我使用了这些模型类:

public class MapHeader
{
    public int MapHeaderId { get; set; }

    public virtual List<MapDetail> MapDetails { get; set; }
}

public class MapDetail
{
    public int MapDetailId { get; set; }

    public int MapHeaderId { get; set; }
    public virtual MapHeader MapHeader { get; set; }
}

然后我写了一个简单的命令行程序来保存一些数据并从数据库中读回:

private static void InsertMapHeader()
{
    var header = new MapHeader
    {
        MapDetails = new List<MapDetail>
        {
            new MapDetail(),
            new MapDetail(),
            new MapDetail(),
            new MapDetail()
        }
    };

    using (var context = new BreakAwayContext())
    {
        context.MapHeaders.Add(header);
        context.SaveChanges();
    }
}

private static void ReadMapDetails()
{
    using (var context = new BreakAwayContext())
    {
        var detail = context.MapDetails.FirstOrDefault();
        Console.WriteLine("Header id: {0}", detail.MapHeader.MapHeaderId);
    }
}

此代码获取第一个 MapDetail 并跟随导航属性到 MapHeader。所有这些都可以正常工作,因为 Code-First 在请求时使用延迟加载来获取 MapHeader 导航属性。

如果您想急切地加载依赖属性,您可以更改查询以使用 Include 方法加入 MapHeaders 表,如下所示:

var detail = context.MapDetails.Include(d => d.MapHeader).FirstOrDefault();

您仍然没有显示查询的代码(它可能在您的 Control 类中),因此很难说出确切的问题可能是什么。

【讨论】:

  • pedro 我也添加了我的查询这个查询在一个存储过程中
  • 我也无法在我的结果集 EF v 6.1.3 中找到 Include 方法
  • 好的,不要关闭延迟加载。使用存储过程,您需要将 MapHeader 表加入到您的结果中(就像您加入的其他表一样),以便 EF 也将创建该 Navigation 属性。
  • 你的意思是在查询中..ok
  • 是的,在您的查询中。
【解决方案2】:

这不是理想的方式,但无论如何它让我通过了.. 我从存储库中加载了特定的 mapheader,然后手动填充列表中的每个 mapdetail 对象

控制器

   MapHeaderRepository repMapHeader = new MapHeaderRepository("name=ge");
   MapDetailsRepository repMapDetail = new MapDetailsRepository("name=ge");

   MapDetailResultSet mapDetailResultSet = repMapDetail.FindMapDetails(mapHeaderId, yearId, classIds, 
                                                    indicatorGroup, indicatorIds);
   var mapHeader = repMapHeader.Get(22);

   foreach (MapDetail md in mapDetailResultSet.mapDetails)
   {
        md.mapheader = mapHeader;
   }

【讨论】:

    猜你喜欢
    • 2012-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-12
    • 1970-01-01
    • 2017-09-22
    • 2019-11-20
    • 1970-01-01
    相关资源
    最近更新 更多