【问题标题】:How to save data with EF in the right way (multiple tables)如何用EF正确保存数据(多表)
【发布时间】:2019-05-15 16:02:53
【问题描述】:

例如,您有两个通过 ICollection 属性连接(代码优先)的表。

public class EntityEnviroment
{
    [Key]
    public virtual int env_id { get; set; }

    public virtual string env_name { get; set; }

    public virtual string env_country { get; set; }

    public virtual ICollection<StcEntityFailedReportDetail> failedReportDetails { get; set; }
}

public class EntityFailedReportDetail
{
    [Key]
    public virtual int failed_reports_details_id { get; set; }

    public virtual int report_id { get; set; }

    public virtual string report_status { get; set; }

    public virtual StcEntityEnviromentStatus StcEntityEnviromentStatus { get; set; }
}

对于一个表,我为我的条目创建了一个上下文实例,然后我添加了它。最后我保存了它。对于多个表,我这样做了:

        using (var db = new StatusPlatformContext())
        {
            var entryDetail = new EntityFailedReportDetail();
            foreach (var value in result.failed_report_details)
            {

                entryDetail.report_id = value.report_id;
                entryDetail.report_status = value.report_status;

                db.StcEntityFailedReportDetails.Add(entryDetail);

            }

            var entry = new EntityEnviroment
            {
                env_name = result.environment_status.env_name,
                env_country = "Ger",
                failedReportDetails = new List<EntityFailedReportDetail> { entryDetail }
            };
            entryDetail.EntityEnviroment = entry;
            db.EntityEnviromentStat.Add(entry);
            db.SaveChanges();
        }

如果我这样做,只会保存最后一个详细信息条目。如果我将 db.SaveChanges() 添加到 foreach 中,我只会在三个详细信息行中的最后一个的外键列中获得一个条目。

我应该如何构建代码?我发现的所有示例都只显示一个表而不是多个表。有没有我应该阅读的模式示例?

谢谢

【问题讨论】:

标签: c# entity-framework


【解决方案1】:

有两个问题

1) 您需要为每个结果创建一个新的 EntityFailedReportDetail。

2) 此外,将每个 EntityFailedReportDetail 添加到 EntityEnvironment 中。

试试这个:

        var entry = new EntityEnviroment
        {
            env_name = result.environment_status.env_name,
            env_country = "Ger",
            failedReportDetails = new List<EntityFailedReportDetail>()
        };

        foreach (var value in result.failed_report_details)
        {
            var entryDetail = new EntityFailedReportDetail();
            entryDetail.report_id = value.report_id;
            entryDetail.report_status = value.report_status;

            entry.failedReportDetails.Add(entryDetail);

        }

【讨论】:

  • 与此相同有很大帮助并且有效。非常感谢
  • @0x53olution 很高兴这有帮助:)
【解决方案2】:

对于包含其他实体集合的实体,您应该在构造时初始化这些集合:

public class EntityEnviroment
{
    [Key]
    public virtual int env_id { get; set; }
    public virtual string env_name { get; set; }
    public virtual string env_country { get; set; }
    public virtual ICollection<StcEntityFailedReportDetail> failedReportDetails { get; set; } = new List<StcEntityFailedReportDetail>();
}

这样一来,您就可以在新实体上使用这些集合。代码中任何“设置”集合的地方都应该被标记为调查。例如,这不是一种从数据库中清除集合的方法,因此,如果除此之外的任何地方(或构造函数)执行= new List&lt;TEntity&gt;(),这就是一个问题。

var entryDetail = new EntityFailedReportDetail();
foreach (var value in result.failed_report_details)
{
    entryDetail.report_id = value.report_id;
    entryDetail.report_status = value.report_status;
    db.StcEntityFailedReportDetails.Add(entryDetail);
}

此代码的问题是您正在初始化 1 个“详细信息”记录,然后在循环中更新其详细信息并尝试将其“添加”到 DbSet。这是一个单一的参考。

然后这段代码:

failedReportDetails = new List<EntityFailedReportDetail> { entryDetail }

只需使用您添加的最新详细信息的那个引用来初始化一个集合。

调整你的例子:

using (var db = new StatusPlatformContext())
{
    var entry = new EntityEnviroment
    {
        env_name = result.environment_status.env_name,
        env_country = "Ger",
    };

    foreach (var value in result.failed_report_details)
    {
        var entryDetail = new EntityFailedReportDetail
        {
            report_id = value.report_id,
            report_status = value.report_status,
            EntityEnvironment = entry
        };
        entry.failedReportDetails.Add(entryDetail);
    }

    db.EntityEnviromentStat.Add(entry);
    db.SaveChanges();
}

您不需要将每个详细信息显式添加到上下文的详细信息 DbSet 中,并且如果您不需要在条目之外查询详细信息,则您的上下文甚至不需要详细信息 DbSet。 EF 将管理相关实体,因此您只需要“顶级”实体的 DbSet,基本上是系统单独引用的父实体。您始终可以通过其父级查询相关实体。

【讨论】:

  • 感谢您的帮助,这解释了很多,现在可以使用了。
猜你喜欢
  • 2016-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多