Как правильно сохранять данные с помощью EF (несколько таблиц)

Например, у вас есть две таблицы, которые вы связываете (сначала код) свойством 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, я просто получу запись в столбце foreigen key для последней из трех строк подробностей.

Как я должен структурировать код? Все примеры, которые я нашел, показывают только одну таблицу, а не несколько. Есть ли пример с шаблоном, что я должен прочитать?

Спасибо

Всего 2 ответа


Есть две проблемы

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);

        }

Для сущностей, которые содержат коллекции других сущностей, вы должны инициализировать эти коллекции при создании:

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<TEntity>() что является проблемой.

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 будет управлять связанными сущностями, поэтому вам нужны только DbSets для сущностей «верхнего уровня», в основном родительских сущностей, на которые ваша система ссылается индивидуально. Вы всегда можете запросить связанные сущности через их родителей.


Есть идеи?

10000