EF Core 多对一:添加新元素会删除所有其他条目

Posted

技术标签:

【中文标题】EF Core 多对一:添加新元素会删除所有其他条目【英文标题】:EF Core Many-To-One: Adding new Element deletes all other Entries 【发布时间】:2021-12-23 22:32:18 【问题描述】:

我有一个简单的多对一关系:

public class Company

    public IEnumerable<User> Users  get; set; 

    public int Id  get; set; 


public class User

    public int CompanyId  get; set; 

    [Required]
    public Company Company  get; set; 

    public int Id  get; set; 

我还尝试将我的用户定义为以下(没有成功):

public class User

    [Required]
    [ForeignKey("Company")]
    public int CompanyId  get; set; 

    public virtual Company Company  get; set; 

    public int Id  get; set; 

我有以下方法将新用户添加到公司:

public async Task<bool> Add(User user)

    try
    
        await this.context.Set<User>().AddAsync(user);
        await this.context.SaveChangesAsync();
        return true;
    
    catch (Exception)
    
        return false;
    

我这样称呼这个方法:

var company = await this.companyService.Get(1); // this works
if (company == null)

    return;


await this.userService.Add(
                           new User
                           
                               CompanyId = company.Id,
                               Company = company, // I also tried to remove this line - no effect
                           );

我的 DbContext 如下所示:

public class AppContext : IdentityDbContext

    public AppContext(DbContextOptions<AppContext> options)
    : base(options)
    
    

    public DbSet<Company> Company  get; set; 

    public DbSet<User> User  get; set; 


既然我已经解释了场景,那么问题就来了。当我将用户添加到公司时,所有条目都将被删除。 “删除”是什么意思?整个表“用户”是空的,没有任何条目。在我添加用户并检查 company 之前,我可以看到所有用户。如果我在插入后再次获取公司,则属性 Users 返回一个空列表(非空)。这也会影响值的删除和更新。我已经在这个问题上坐了 3 天,完全不知道我做错了什么。

【问题讨论】:

【参考方案1】:

经过 30 小时的调试,我发现了问题所在。它与 EF 无关(我在某种程度上预料到了,因为我确实复制并粘贴了整个文档 5 次)。

也许有人有类似的问题,所以我在这里发布我的答案,但请注意,这高度特定于我的用例。

我将当前登录的用户存储在ProtectedSessionStorage 中,如下所示:

await this.protectedSessionStorage.SetAsync("user", await this.userService.Get(id));

无论出于何种原因(我又搜索了 2 个小时),我的一些属性被忽略并且未正确存储(即属性 Company.Users),即使我没有使用任何解释此行为的注释。当我再次加载这个确切的用户时,出于其他未知原因,EF 认为(因为缺少 Company.Users 属性)公司没有任何用户。同样,文档中没有描述这种行为,我发现没有人遇到这种特定问题,所以我可能做了一些描述这种行为的事情。

解决方法:取Json.NET from Newtonsoft,将其序列化,然后将序列化后的字符串存储在受保护的会话存储中。我真的只是改变了这一点,一切都按预期工作。当然,当我访问存储时,我必须反序列化所有内容。

await this.protectedSessionStorage.SetAsync("user", JsonConvert.SerializeObject(await this.userService.Get(id)));

【讨论】:

【参考方案2】:

试试这个类(如果你使用 ef core 5+,你可以省略数据注释)


public class User
 
   [Key]
   public int Id  get; set; 

    [Required]
    public int? CompanyId  get; set; 

   [ForeignKey(nameof(CompanyId ))]
   [InverseProperty("Users")]
    public  virtual Company Company  get; set; 


public class Company

  [Key]
  public int Id  get; set; 

  [InverseProperty(nameof(User.Company))]
  public virtual ICollection<User> Users  get; set; 
 

和代码

var company = await this.companyService.Get(1); 

await this.userService.Add(new User  CompanyId = company.Id);

public async Task<bool> Add(User user)

    try
    
       context.Set<User>().Add(user);
        await context.SaveChangesAsync();
        return true;
    
    catch (Exception)
    
        return false;
    


【讨论】:

现在奇怪的是,它在调试器中看起来没问题,当我检查公司时,添加一个用户然后再次检查。但是当我稍后(如在另一个视图中)再次检查(没有调用任何添加/更新/删除)时,数据又消失了。如果我发现了错误,我会多观察一下,然后再回来。 目前它似乎无法解决我的问题。如果我注释掉“添加”,一切都会按预期工作。但是一旦添加了用户,一切都是空的。

以上是关于EF Core 多对一:添加新元素会删除所有其他条目的主要内容,如果未能解决你的问题,请参考以下文章

EF Core 5,删除多对多关系

EF Core 5.0 - 更新 ASP.NET Core Web API 中的多对多实体

EF Core 过滤掉多对多关系中的重复实体

定义引用同一个表的多对多关系(EF7/core)

使用 EF Core 保存附加实体时如何删除子实体

EF Core 中的一对一关系(无法确定一对一关系的子/依赖方)