【问题标题】:Auto increment non key value entity framework core 2.0自增非键值实体框架核心2.0
【发布时间】:2018-02-07 13:33:48
【问题描述】:

我有一个对象,它有一个存储为 GUID 和友好 ID 的密钥,如下所示:

public class Job {

    [Key]
    public Guid Id { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int FriendlyId { get; set; }

    public string Description { get; set; }
}

但是,当我尝试使用我的更新方法更新描述时:

    public void Update(Job job, Job jobParam) {
        if (job == null) {
            throw new AppException("Job does not exist");
        }

        //Update job properties
        job.Description = jobParam.Description;


        _context.Job.Update(job);
        _context.SaveChanges();
    }

我收到一条错误消息:

System.Data.SqlClient.SqlException:无法更新标识列 'FriendlyId'

我已确保尝试更新正确的对象,但我不明白为什么friendlyID 在未更改时会尝试更新。在网上查看时,我可以看到 EF core 1.1 中存在一个会导致此问题发生的错误,但与 2.0 或不是键的值无关。

【问题讨论】:

  • 请分享这个方法Job.Update(job);
  • 这是一种内置的上下文方法。这不是我的代码,而是 EF。

标签: c# entity-framework .net-core entity-framework-core


【解决方案1】:

EF Core 中生成的属性的确切行为仍在调整过程中。 EF Core 2.0 引入了两个新的属性元数据属性 - BeforeSaveBehaviorAfterSaveBehavior。没有用于设置它们的数据注释/流利的 API,默认情况下,它们隐含在值生成策略中,以及属性是否是键的一部分。同时它们会影响跟踪操作的行为。

这里的问题是,对于不是键的身份列(即ValueGeneratedOnAdd),AfterSaveBehaviorSave,这反过来使Update 方法将它们标记为已修改,从而生成错误的UPDATE 命令。

要解决这个问题,您必须像这样设置AfterSaveBehavior(在OnModelCreating 覆盖内):

modelBuilder.Entity<Job>()
    .Property(e => e.FriendlyId)
    .ValueGeneratedOnAdd()
    .Metadata.AfterSaveBehavior = PropertySaveBehavior.Throw; // <--

更新:在 EF Core 3.0+ 中,许多元数据属性已替换为 Get/Set 方法,因此只需使用相应的方法即可:

.Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Throw);

【讨论】:

  • 谢谢!这解决了问题。你有关于这方面的文档的链接吗?找了好久都没用。
  • 未直接 - 在Setting Explicit Values for Generated Properties 中部分提及。唯一可靠的来源是源代码:(
  • 对我不起作用:在命令 add-migration 我得到错误“...每个表只能配置一列为 'Identity'...”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-06
  • 2021-09-03
  • 2020-07-08
  • 1970-01-01
  • 2021-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多