【问题标题】:Entity Framework context SaveChanges throwing NULL error实体框架上下文 SaveChanges 抛出 NULL 错误
【发布时间】:2020-09-16 05:04:20
【问题描述】:

我已在上下文模型中添加了一个项目并尝试保存更改,但即使使用有效值,我也会收到如下错误。想知道它是如何在拥有所有有效值之后抛出的。

System.Data.Entity.Infrastructure.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。

System.Data.Entity.Core.UpdateException:更新条目时出错。有关详细信息,请参阅内部异常。

Oracle.ManagedDataAccess.Client.OracleException: ORA-01400: 不能 将 NULL 插入 ("DBO"."JOBS"."JOBID")

代码:

_dbContext.Jobs.Add(new Job(){JobId = 1902456,JobExecutionId = 390023,AccountId = 1,CommandType = "Type 1"});
_dbContext.SaveChanges();

internal class JobsConfiguration : EntityTypeConfiguration<Job>
{
        public JobsConfiguration()
        {
            ToTable("JOBS");
            HasKey(g => g.JobId);
            Property(g => g.JobId).HasColumnName("JOBID");
            Property(g => g.JobExecutionId).HasColumnName("JOBEXECUTION_ID");
            Property(g => g.AccountId).HasColumnName("ACCTID");
            Property(g => g.CommandType).HasColumnName("COMMANDTYPE");
        }
}

【问题讨论】:

  • EF 可能希望数据库为 PK 分配一个值。
  • @JeremyLakeman 嗨,当我通过代码中的直接查询插入相同的数据时,我没有遇到任何问题并且插入了数据。谢谢。
  • Entity Framework 正在传递 NULL,因为您告诉它 JobId 字段是主键。它没有使用你给它的价值。 Oracle 也很“特殊”,因为您必须自己告诉它如何自动增加 ID。是的,这很愚蠢,但 Oracle 就是这样。
  • 在您的构建器中使用这段代码:Property(e => e.JobId).HasColumnName("JOBID") .ForOracleUseSequenceHiLo("SEQUENCE_NAME");
  • @CaptainKenpachi 存在另一列“ID”,用于自动递增。

标签: c# oracle entity-framework


【解决方案1】:

当您使用 dbContext.Entity.Add(...) - 您的实体 PK (JobId) 必须为零,因为 Add() 是插入新值。 如果您想修改 PK 不为零的实体,请改用 dbContext.Entity.Update(...)

那么你的第一个字符串必须是:

_dbContext.Jobs.Add(new Job(){JobId = 1902456,JobExecutionId = 390023,AccountId = 1,CommandType = "Type 1"});

PS 如果您使用带有零 PK 的 Update() - 它会在表中插入新值(当您使用 Add() 时),例如:

_dbContext.Jobs.Update(new Job(){JobId = 0,JobExecutionId = 390023,AccountId = 1,CommandType = "Type 1"});

【讨论】:

  • 他正在尝试添加新项目,而不是修改现有项目。对于更新 Jobs.Update(..) 代码是可以的。但是你能指定他在插入时如何避免在 jobId 处出现 null 吗?
  • 如果 PK 不为零 - 它已经不是新项目。 Job?.JobId - Add(JobId != 0) 时为 NULL
【解决方案2】:

您必须告诉 Oracle 使用序列来存储和更新自增的 PK。这是我认为 Oracle 独有的东西:

internal class JobsConfiguration : EntityTypeConfiguration<Job>
{
        public JobsConfiguration()
        {
            ToTable("JOBS");
            HasKey(g => g.JobId);
            Property(g => g.JobId).HasColumnName("JOBID")
                                  .ForOracleUseSequenceHiLo("JOBS_SEQUENCE");//can be any name
            Property(g => g.JobExecutionId).HasColumnName("JOBEXECUTION_ID");
            Property(g => g.AccountId).HasColumnName("ACCTID");
            Property(g => g.CommandType).HasColumnName("COMMANDTYPE");
        }
}

【讨论】:

  • 有另一个单独的列“ID”用于自动递增,JOBID 是在代码中生成并插入的唯一值。
  • 移除 HasKey(g => g.JobId);
  • 是的,我已经尝试过了,但最终出现了像 HasKey 这样的错误应该有类似的东西
  • 具有讽刺意味的是它之前工作过,但突然停止插入记录并给出上述错误。 :(
【解决方案3】:

您在 cmets 中提到该表有一个 id 列。也许这会导致您遇到错误,afaik EF 隐含地假定这是主键。一种解决方案可以是为 JobsId 创建唯一索引,而不是使其成为主键或显式忽略 id 属性。在 EF Core 中,唯一索引是这样完成的:

entity.HasIndex(e => e.JobsId)
      .HasName("SYS_C00296922")
      .IsUnique();

entity.Property(e => e.JobsId)
      .HasColumnName("JobsId");

对于 EF 6.1 的描述如下:

https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/fluent/types-and-properties

这里描述了如何忽略 EF Core 和 EF 6 的属性:https://stackoverflow.com/a/10385738/4712865

【讨论】:

    猜你喜欢
    • 2021-11-15
    • 2016-09-05
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多