【问题标题】:Create a Parent with existing children in EntityFramework core在 EntityFramework 核心中创建具有现有子级的父级
【发布时间】:2017-05-30 20:26:21
【问题描述】:

我正在构建一个 Web API 并且有两个模型:任务和功能:

public class Feature
{
    [Key]
    public long FeatureId { get; set; }
    public string Analyst_comment { get; set; }

    public virtual ICollection<User_Task> Tasks { get; set; }

    public Feature()
    {

    }
}

public class User_Task
{
    [Key]
    public long TaskId { get; set; }
    public string What { get; set; }

    [ForeignKey("FeatureId")]
    public long? FeatureId { get; set; }


    public User_Task()
    {

    }

}

我首先创建任务,然后创建一个结合了其中几个任务的功能。任务创建成功,但是在使用现有任务创建功能时,我的控制器会抛出错误,指出任务已存在:

我的 FeatureController 有以下方法:

//Create
[HttpPost]
public IActionResult Create([FromBody] Feature item)
{
    if (item == null)
    {
        return BadRequest();
    }

    ** It basically expects that I am creating a Feature with brand new tasks, so I guess I will need some logic here to tell EF Core that incoming tasks with this feature already exist **

    _featureRepository.Add(item);

    return CreatedAtRoute("GetFeature", new { id = item.FeatureId }, item);
} 

如何告诉 EF 核心,传入的功能具有已经存在的任务,它只需要更新引用而不是创建新的?

我的背景:

public class WebAPIDataContext : DbContext
{
    public WebAPIDataContext(DbContextOptions<WebAPIDataContext> options)
        : base(options)
    {
    }

    public DbSet<User_Task> User_Tasks { get; set; }
    public DbSet<Feature> Features { get; set; }

}

和回购:

public void Add(Feature item)
{
    _context.Features.Add(item);
    _context.SaveChanges();
}

【问题讨论】:

  • 您是否已经尝试附加它?不知道您的存储库实现如何以及它返回什么,因此您可以在存储库中执行附件(在 AddOrUpdate 方法中?)。 context.Attach(item) 应该附加一个分离的项目。原因是 EF Core 基于 changetracker 跟踪项目。当一个项目不在跟踪器中并且您调用“.Add”时,它会将其视为插入。当您附加它时,它将查看实体是否存在,如果存在,则将其加载到跟踪器中,然后跟踪更改并执行更新
  • 我已经用上下文和 repo 类方法更新了我的问题。也许现在你能准确指出我能做什么吗?
  • _context.Attach(item) 之前(或代替)context.Features.Add(item) 解决了吗?
  • 另见docs ASP.NET Core + EF Core 的示例和推荐用法
  • 把它放在 Add() 之前给出算术异常,把它放在 Add() 之后也会抛出一个异常。当我使用而不是 Add() 时,没有错误,我得到了响应(得到 featureId=0 的功能),但在数据库中没有创建任何内容

标签: asp.net-core entity-framework-core


【解决方案1】:

当对带有未从 EF 加载的模型的 DBSet 调用 Add 时,它认为它未被跟踪并始终假定它是新的。

相反,您需要从 dbcontext 加载现有记录,并将传递到 API 的数据中的属性映射到现有记录。通常这是从参数对象到域的手动映射。然后,如果您返回一个对象,则将该新域对象映射到 DTO。您可以使用 AutoMapper 等服务将域映射到 DTO。完成映射后,只需调用 SaveChanges。

一般来说,加载记录和映射字段对于 API 的安全性是一件好事。你不会想假设传入的数据是原始和诚实的。当您授予调用代码访问实体所有属性的权限时,您可能不会期望它们更改所有字段,并且其中一些字段可能是敏感字段。

【讨论】:

  • 不,不!不要使用 Automapper 从 DTO 映射回持久性对象 (DAO)!仅来自 DAO -> DTO 或 Domain -> DTO/ViewModel。永远不要反过来。 AutoMapper 不是为此而设计的,它在大多数重要的情况下都不起作用,请参阅this,它永远不会以良好的方式结束并造成更多的麻烦,然后节省
  • 冷静下来……这不是本意。我将编辑答案以澄清这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多