“EF Core 7.0 错误: 在已经指定的情况下,将实体种子添加到 ‘X’ 并指定外键值”

huangapple go评论76阅读模式
英文:

EF Core 7.0 Error: "Add the entity seed to 'X' and specify the foreign key values" when already specified

问题

我在种植单向关系方面遇到了问题。种植看起来如下:

  • 用户 1 --> * 帖子

我在配置上收到了这个错误:

未处理的异常。System.InvalidOperationException:不能添加实体类型为 'User' 的种子实体,因为它具有设置的导航 'Posts'。要种子关系,请将实体种子添加到 'Post' 并指定外键值 {'UserId'}。

对我来说,这个错误毫无意义,因为我已经明确指定了外键值 Post.UserId...

任何帮助都将不胜感激!

这是我的配置:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Models.User>()
        .HasMany(user => user.Posts)
        .WithOne()
        .HasForeignKey(post => post.UserId)
        .IsRequired(false);

    Models.User user = new() { Id = 1, Username = "user" };
    Models.Post post = new() { Id = 1, Body = "Hello from the other side", UserId = 1 };
    user.Posts.Add(post);

    modelBuilder.Entity<Models.User>().HasData(user);
    modelBuilder.Entity<Models.Post>().HasData(post);
}

这是我的类定义:

public abstract class Base
{
    [Key]
    public int Id { get; set; }
    public DateTime CreatedAt { get; set; } = DateTime.Now;
    public DateTime? UpdateAt { get; set; }
}

public class Post : Base
{
    [Required] public string Body { get; set; }
    public int? UserId { get; set; }
}

public class User : Base
{
    [Required] public string Username { get; set; }
    [ForeignKey(nameof(Post.UserId))] public ICollection<Post> Posts { get; set; } = new List<Post>();
}

希望这对你有所帮助。

英文:

I am having trouble seeding unidirectional relationships. The seeding looks as follows:

  • User 1-->* Post

I'm receive this error on configuration

> Unhandled exception. System.InvalidOperationException: The seed entity for entity type 'User' with the key value 'Id:1' cannot be added because it has the navigation 'Posts' set. To seed relationships, add the entity seed to 'Post' and specify the foreign key values {'UserId'}.

This error makes no sense to me, as I am already explicitly specifying the foreign key value Post.UserId...

Any help is much appreciated!

Here is my configuration

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity&lt;Models.User&gt;()
        .HasMany(user =&gt; user.Posts)
        .WithOne()
        .HasForeignKey(post =&gt; post.UserId)
        .IsRequired(false);

    Models.User user = new() { Id = 1, Username = &quot;user&quot; };
    Models.Post post = new() { Id = 1, Body = &quot;Hello from the other side&quot;, UserId = 1 };
    user.Posts.Add(post);

    modelBuilder.Entity&lt;Models.User&gt;().HasData(user);
    modelBuilder.Entity&lt;Models.Post&gt;().HasData(post);
}

And here are my class definitions

public abstract class Base
{
    [Key]
    public int Id { get; set; }
    public DateTime CreatedAt { get; set; } = DateTime.Now;
    public DateTime? UpdateAt { get; set; }
}

public class Post : Base
{
    [Required] public string Body { get; set; }
    public int? UserId { get; set; }
}

public class User : Base
{
    [Required] public string Username { get; set; }
    [ForeignKey(nameof(Post.UserId))] public ICollection&lt;Post&gt; Posts { get; set; } = new List&lt;Post&gt;();
}

答案1

得分: 0

我发现了我的实现中的错误,如果有人遇到相同的问题。

在创建阶段,您不应该填充虚拟集合,即在这种情况下的 User.Posts,因为外键是 EF 用来在稍后填充集合的。基本上删除 user.Posts.Add(post);

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Models.User>()
        .HasMany(user => user.Posts)
        .WithOne()
        .HasForeignKey(post => post.UserId)
        .IsRequired(false);

    Models.User user = new() { Id = 1, Username = "user" };
    Models.Post post = new() { Id = 1, Body = "Hello from the other side", UserId = 1 };

    modelBuilder.Entity<Models.User>().HasData(user);
    modelBuilder.Entity<Models.Post>().HasData(post);
}

此外,EF 在幕后实现了延迟加载,因此在从数据库获取数据时,您必须包括虚拟集合以填充它们。这在 repositories/User.cs 中体现:

public static Models.User? Get(string username)
{
    using Contexts.Main context = new();
    return context.Users.Include(user => user.Posts).SingleOrDefault(user => user.Username == username);
}
英文:

I found the error in my implementation for anyone experiencing the same.

In the creation phase, you are not supposed to populate virtual collections, in this case User.Posts, as the foreign key is what EF uses to populate the collections later on. Basicailly remove user.Posts.Add(post);

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity&lt;Models.User&gt;()
        .HasMany(user =&gt; user.Posts)
        .WithOne()
        .HasForeignKey(post =&gt; post.UserId)
        .IsRequired(false);

    Models.User user = new() { Id = 1, Username = &quot;user&quot; };
    Models.Post post = new() { Id = 1, Body = &quot;Hello from the other side&quot;, UserId = 1 };

    modelBuilder.Entity&lt;Models.User&gt;().HasData(user);
    modelBuilder.Entity&lt;Models.Post&gt;().HasData(post);
}

On top of that, EF implements lazy loading behind the scenes, so when fetching data from the DB, you must include your virtual collections to populate them. This is in repositories/User.cs:

public static Models.User? Get(string username)
{
    using Contexts.Main context = new();
    return context.Users.Include(user =&gt; user.Posts).SingleOrDefault(user =&gt; user.Username == username);
}

huangapple
  • 本文由 发表于 2023年5月24日 21:40:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76324190.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定