繁体   English   中英

实体框架核心:将具有列表的对象添加到DbContext会导致列表为空

[英]Entity Framework Core: Adding an object with a List to a DbContext results in an empty List

我们正在尝试将实体框架模型保存到数据库中。

在模型中,轨道始终包含一条消息,并且一条消息的重传列表中可能包含任意数量的消息。

保存模型时,我们检查数据库中是否已存在Track模型; 如果没有,我们只需将Track添加到DbContext。

public class Track
{
    [Key]
    public Guid TrackId { get; set; }
    public virtual Message Message { get; set; }
}

public class Message
{
    [Key]
    public Guid MessageId { get; set; }
    public Guid TrackId { get; set; }

    public virtual List<Message> Retransmits { get; set; }
}

public void Save (Track track)
{
    using (var context = new DatabaseContext())
    {
        Track foundTrack = Read(track.TrackId); // Returns a Track if it already exists in the database

        if (foundTrack == null)
        {
            context.Add(track);
        }
        else
        {
            // Update the Track. Not relevant to this question
        }

        context.SaveChanges();
    }
}

// Returns a Track if it exists in the database or null
public Track Read(Guid trackId)
{
    using (var context = new DatabaseContext())
    {
        return context.Tracks
            .Include(t => t.Message)
                .ThenInclude(m => m.Retransmits)
                .FirstOrDefault(t => t.TrackId == trackId);
    }
}

将Track添加到DbContext实体框架时,将始终清除“重传列表”。 这意味着,在调用DbContext.Add之前,消息可以在其重传列表中包含一个消息,但是在调用DbContext.Add之后,它将突然变为0。实体框架实际上是在清除列表,而不是将其添加到数据库中。

我们期望重传列表将添加到DbContext中,并且不会在没有警告的情况下从模型中删除。

在调试过程中,我们发现将重发List<Message>List<Message>更改为List<AnyOtherObject>返回预期的结果和数据库中的行。

似乎因为重传列表与它所包含的类具有相同的类型(即,一条消息可以包含许多消息),所以实体框架将其区别对待。

我们还尝试在实体之间配置一对多关系,其中modelBuilder.Entity<Message>().HasMany(m => m.Retransmits)没有区别。 甚至是modelBuilder.Entity<Message>().HasMany(m => m.Retransmits).WithOne(m => m.Parent) ,其中Parent是对重传消息的包含对象的引用。 但是,这导致了StackOverflow异常。

实体框架拒绝将列表添加到数据库的原因可能是什么? 有什么方法可以配置实体框架以允许消息包含重传列表(消息类型为Message),并按预期将其添加到数据库中? 还是我们完全在做错事?

我已在Visual Studio的调试器中附加了行为的图像。

编辑:我们已经尝试了最新的稳定的Entity Framework Core 2.2.6版以及Entity Framework Core 3.0.0版-预览版9。两个版本中都存在相同的行为。

编辑编辑:以下代码初始化模型,并应重现该问题。

public void ReproduceIssue ()
{
    // Create a Track and Message
    Track track = new Track()
    {
        Message = new Message()
    };

    track.Message.TrackId = track.TrackId;

    // Create a Retransmitted Message
    Message retransmit = new Message()
    {
        TrackId = track.TrackId
    };

    // Add the Retransmitted Message to the List
    track.Message.Retransmits.Add(retransmit);

    Save(track);
}

我们对模型进行了一些更改。 尽管我相信Entity Framework在发布警告/异常之前绝不应该丢掉任何信息,但我们确实避免了该问题。

我想发布代码,但是由于最初的问题遗漏了很多代码细节,所以它有点复杂。 但是,解决方案基本上是使用联接表在消息之间配置多对多关系。

此后,它的表现符合预期。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM