【问题标题】:Entity Framework 6.1: update child ICollection when the parent entity is created实体框架 6.1:创建父实体时更新子 ICollection
【发布时间】:2021-02-19 08:28:21
【问题描述】:

我必须将一些数据从源数据库传递到另一个目标数据库,这两个目标数据库都使用实体框架处理,只有两个不同的DbContexts

这是我的代码:

internal async static Task UploadNewsList(DateTime dataStart, TextWriter logger)
{
    try
    {
        NumberFormatInfo provider = new NumberFormatInfo();
        provider.NumberDecimalSeparator = ".";

        using (BDContentsDataModel buffettiContext = new BDContentsDataModel())
        {
            List<News> newsList = buffettiContext.News.Where(x => x.Online && x.DataPub >= dataStart.Date).ToList();
            using (DirectioDBContext directioContext = new DirectioDBContext())
            {
                foreach(News buffettiNews in newsList)
                {
                    bool hasAuth = false;
                    List<DirectioAutore> listAutori = null;
                    List<DirectioAutore> listAutoriFinal = new List<DirectioAutore>();

                    if (buffettiNews.AutoreList?.Count > 0)
                    {
                        hasAuth = true;
                        listAutori = EntitiesHelper.GetAutoriDirectio(buffettiNews.AutoreList.ToList(), directioContext);
                        foreach (var autore in listAutori)
                        {
                            int dirAuthId = 0;
                            bool exist = false;
                            foreach (var dirAut in directioContext.Autori)
                            {
                                if (dirAut.Nome.IndexOf(autore.Nome, StringComparison.InvariantCultureIgnoreCase) >= 0 &&
                                    dirAut.Cognome.IndexOf(autore.Cognome, StringComparison.InvariantCultureIgnoreCase) >= 0)
                                {
                                    exist = true;
                                    dirAuthId = dirAut.Id;
                                }
                            }
                                //directioContext.Autori.
                                //Where(x => autore.Cognome.ToLowerInvariant().Contains(x.Cognome.ToLowerInvariant()) &&
                                //         autore.Nome.ToLowerInvariant().Contains(x.Nome.ToLowerInvariant())).Any();

                            if (!exist)
                            {
                                directioContext.Autori.Add(autore);
                                directioContext.SaveChanges();
                            }
                            else
                            {
                                autore.Id = dirAuthId;
                            }

                            listAutoriFinal.Add(autore);
                        }
                    }

                    DirectioNews directioNews = EntitiesHelper.CreateDirectioNewsModel(buffettiNews);
                    if (hasAuth)
                        directioNews.AutoreList = listAutoriFinal;

                    if (directioNews == null)
                        throw new Exception("[News] - Trasformazione entità fallita");

                    directioContext.News.Add(directioNews);
                    await directioContext.SaveChangesAsync();
                }
            }
        }
    }
    catch (Exception ex)
    {
        logger.WriteLine(ex.Message);
        throw ex;
    }
}

这是目标DbContext

public class DirectioDBContext : DbContext
{
    public DirectioDBContext() : base("name=DirectioCMSDataModel") { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        // ...
        
        modelBuilder.Entity<DirectioNews>()
            .HasMany(s => s.AutoreList)
            .WithMany(x => x.News)
            .Map(cs =>
            {
                cs.MapLeftKey("Autore_Id");
                cs.MapRightKey("News_Id");
                cs.ToTable("NewsAutore");
            });
    }

    public virtual DbSet<DirectioNews> News { get; set; }
    public virtual DbSet<DirectioVideo> Video { get; set; }
    public virtual DbSet<DirectioMedia> Media { get; set; }
    public virtual DbSet<DirectioAutore> Autori  { get; set; }
    public virtual DbSet<DirectioVideoAutori> VideoAutori { get; set; }
}

这是感兴趣的目标父模型:

[Table("News")]
public partial class DirectioNews
{
    [Key]
    public int Id { get; set; }

    public string Titolo { get; set; }

    public int IdDocType { get; set; }

    public string Abstract { get; set; }

    public string Testo { get; set; }

    [Required]
    public DateTime DataPub { get; set; }

    public int IdUmbraco { get; set; }

    public int CreatedById { get; set; }

    public DateTime CreateDate { get; set; }

    public int? UpdateById { get; set; }
    public DateTime? UpdateDate { get; set; }

    public int? DeletedById { get; set; }
    public DateTime? DeletedDate { get; set; }
    public int? ResumedById { get; set; }
    public DateTime? ResumedDate { get; set; }

    public int? PublishedById { get; set; }
    public DateTime? PublishedDate { get; set; }
    public int? UnpublishedById { get; set; }
    public DateTime? UnpublishedDate { get; set; }

    public DateTime? PublishedFrom { get; set; }
    public DateTime? PublishedTo { get; set; }
    public bool Online { get; set; }
    public bool APagamento { get; set; }
    public int IdConsulenzaOld { get; set; }

    public bool IsDeleted { get; set; }

    public virtual ICollection<DirectioAutore> AutoreList { get; set; }

    public bool IsFromOtherCMS { get; set; } = false;

    public string Name { get; set; }
    public int? NodeId { get; set; }

    public int SortOrder { get; set; } = 0;

    public Guid PlatformGuid { get; set; }

    public Guid SourceGuid { get; set; }

    // Permette l'accesso anche senza login
    public bool FreeWithoutLogin { get; set; }

    // nasconde dalla visualizzazione della lista normale del frontend, visibile solo attraverso l'etichetta campagna
    public bool HideFromList { get; set; }

    #region parametri per riferimenti temporali
    public int? Day { get; set; } = null;
    public int? Month { get; set; } = null;
    public int? Year { get; set; } = null;
    #endregion

    public int? MediaId
    {
        get; set;
    }
}

这是目标子模型

[Table("Autori")]
public class DirectioAutore
{
    [Key]
    public int Id { get; set; }

    public string Nome { get; set; }

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

    public string DescrizioneBreve { get; set; }

    public string Descrizione { get; set; }

    public string Email { get; set; }

    public string Immagine { get; set; }

    public string Tipo { get; set; } // Maschio Femmina Team

    public string Twitter { get; set; }

    public int IdUmbraco { get; set; }

    public bool Online { get; set; }
    public DateTime? PublishedFrom { get; set; }
    public DateTime? PublishedTo { get; set; }
    public int IdOld { get; set; }
    public bool IsDeleted { get; set; }

    public int? NodeId { get; set; }
    public string Name { get; set; }
    public int CreatedById { get; set; } = 1;

    public DateTime CreateDate { get; set; }

    public int? UpdateById { get; set; }
    public DateTime? UpdateDate { get; set; }
    public int? DeletedById { get; set; }
    public DateTime? DeletedDate { get; set; }
    public int? ResumedById { get; set; }
    public DateTime? ResumedDate { get; set; }

    public int? PublishedById { get; set; }
    public DateTime? PublishedDate { get; set; }
    public int? UnpublishedById { get; set; }
    public DateTime? UnpublishedDate { get; set; }

    public string MetaaDescrBreve { get; set; }

    public int? MediaId
    {
        get; set;
    }

    public Guid PlatformGuid { get; set; }

    public Guid SourceGuid { get; set; }

    public string MetaTitle { get; set; }

    public string MetaDescription { get; set; }

    public virtual ICollection<DirectioNews> News { get; set; }
}

EntityFramework 生成了这个表来处理这个many-to-many 关系:

当它保存实体时,它会进入 catch 语句并显示此错误:

INSERT 语句与 FOREIGN KEY 约束“FK_dbo.NewsAutore_dbo.Autori_Autore_Id”冲突。冲突发生在数据库“DirectioContentsCMS_Stage_20201102”、表“dbo.Autori”、列“Id”

可能是什么问题?

非常感谢

【问题讨论】:

  • 错误非常明显 - 很明显,您正尝试将数据插入到 dbo.NewsAutore 中,其中 Autore_Id 的值在引用的表中不存在 (dbo.Autori)。这就是外键的全部目的 - 它在这里完美地完成了它的工作。
  • 你为什么说它不存在?我很确定相关的Autore_Id 实体存在于Autori 表中
  • 错误似乎清楚地说它没有.....
  • 其实是对的,因为我错误地将 LeftKey 和 RightKey 指向上下文。现在我来回答我的问题

标签: c# asp.net-mvc entity-framework entity-framework-6


【解决方案1】:

[已解决]

我错误地将LeftKeyRightKey 指向DbContext,它们没有指向正确的FKs

我刚刚倒了FKs

modelBuilder.Entity<DirectioNews>()
    .HasMany(s => s.AutoreList)
    .WithMany(x => x.News)
    .Map(cs =>
    {
        cs.MapLeftKey("Autore_Id");
        cs.MapRightKey("News_Id");
        cs.ToTable("NewsAutore");
    });

而不是

modelBuilder.Entity<DirectioNews>()
    .HasMany(s => s.AutoreList)
    .WithMany(x => x.News)
    .Map(cs =>
    {
        cs.MapLeftKey("News_Id");
        cs.MapRightKey("Autore_Id");
        cs.ToTable("NewsAutore");
    });

因为MapLeftKey 指向HasMany 方法中指定的navigation property 实体,而MapRightKey 指向@ 的 实体987654332@ 在WithMany 中指定。我的做法正好相反。

然后我在实际保存新闻后移动了关联,以防止创建多个作者:

// ...

DirectioNews directioNews = EntitiesHelper.CreateDirectioNewsModel(buffettiNews);
if (directioNews == null)
    throw new Exception("[News] - Trasformazione entità fallita");

directioContext.News.Add(directioNews);
directioContext.SaveChanges();

if (hasAuth)
{
    List<int> ids = listAutori.Select(s => s.Id).ToList();
    List<DirectioAutore> r = directioContext.Autori.Where(x => ids.Contains(x.Id)).ToList();
    directioNews.AutoreList = r;
    directioContext.SaveChanges();

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    相关资源
    最近更新 更多