微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

实体框架6.1:创建父实体时更新子ICollection

如何解决实体框架6.1:创建父实体时更新子ICollection

我必须将数据从源数据库传递到另一个目标数据库,这两个数据都是使用Entity Framework处理的,只是使用了两个不同的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关系:

many to many rel

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

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

可能是什么问题?

非常感谢

解决方法

[已解决]

我错误地将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指向navigation property方法中指定的HasMany父级实体,而MapRightKey指向父级navigation property中指定的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();

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。