阻止更新EF-core中的导航属性

时间:2017-10-22 15:48:47

标签: entity-framework-core ef-core-2.0

请问在创建新的主要实体时,我们如何阻止EF.core尝试插入/更新外键表?

抛出此异常:

SqlException: Cannot insert explicit value for identity column in table 'clients' when IDENTITY_INSERT is set to OFF.
Cannot insert explicit value for identity column in table 'guards' when IDENTITY_INSERT is set to OFF.
Cannot insert explicit value for identity column in table 'penalties' when IDENTITY_INSERT is set to OFF.

我的代码如下:

  public class Offence
  {
    [Key]
    public Int32 offence_id { get; set; }

    public Int32? guard_id { get; set; }
    public Int32? penalty_id { get; set; }
    public DateTime? dt_recorded { get; set; }
    public Int32? salary_id { get; set; }
    public Decimal? amount { get; set; }
    public String status { get; set; }
    public Int32? site_id { get; set; }

    public Guard Guard { get; set; }
    public Salary Salary { get; set; }
    public Site Site { get; set; }
    public Penalty Penalty { get; set; }
  }

任何创建新Offence的尝试都会产生错误,因为EF.core会尝试为相关的导航属性运行插入操作:

public Guard Guard { get; set; }
public Salary Salary { get; set; }
public Site Site { get; set; }
public Penalty Penalty { get; set; }

我们如何防止这种情况?

编辑:创建和更新代码

[HttpPost]
public async Task<IActionResult> Create([FromBody] Offence o)
{
  if (o == null)
  {
    return BadRequest();
  }

  o.last_modified_by = int.Parse(((ClaimsIdentity)User.Identity).Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value);
  o.last_modified = DateTime.Now;

  await db.AddAsync(o);
  await db.SaveChangesAsync();

  return CreatedAtRoute("GetOffenceAsync", new { id = o.offence_id }, o);
}

3 个答案:

答案 0 :(得分:1)

好像你的导航属性有值,请检查你的导航属性是否有空引用才能保存;如果EF Core保存逻辑具有值,则会尝试保存导航属性。

让我知道这是否有用

答案 1 :(得分:0)

您需要将这些属性设置为virtual。这样,EF知道模型的哪一部分以及什么是导航属性。这也将启用您需要的LazyLoading机制。

public virtual Guard Guard { get; set; }
public virtual Salary Salary { get; set; }
public virtual Site Site { get; set; }
public virtual Penalty Penalty { get; set; }

答案 2 :(得分:0)

要使其正常工作,我必须在保存之前null-out导航属性。

但是,如果使用CreatedAtRoute发回初始对象,则需要缓存nulled-out属性并在返回之前将其添加回来:

实际代码:

[HttpPost]
public async Task<IActionResult> Create([FromBody] Offence o)
{
  if (o == null)
  {
    return BadRequest();
  }

  o.last_modified_by = int.Parse(((ClaimsIdentity)User.Identity).Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value);
  o.last_modified = DateTime.Now;

  var _g = o.Guard;
  var _p = o.Penalty;
  var _s = o.Site;

  o.Guard = null;
  o.Penalty = null;
  o.Site = null;

  await db.AddAsync(o);
  await db.SaveChangesAsync();

  o.Guard = _g;
  o.Penalty = _p;
  o.Site = _s;

  return CreatedAtRoute("GetOffenceAsync", new { id = o.offence_id }, o);
}