简体   繁体   English

实体框架核心 - 无法添加子记录

[英]Entity Framework Core - Can't Add Child records

I have a parent child-relationship and I am unable to use the scaffolding command in EF Core because the the child table has no key.我有父子关系,我无法在 EF Core 中使用脚手架命令,因为子表没有键。 I am not allowed to add keys so I am stuck with the architecture.我不允许添加密钥,所以我坚持使用架构。

When I save the changes, I get the following inner exception: Invalid column name 'NewBusinessMasterNbTransactionId'当我保存更改时,我得到以下内部异常: Invalid column name 'NewBusinessMasterNbTransactionId'

The code in Startup.cs: Startup.cs 中的代码:

  public void ConfigureServices(IServiceCollection services)
  {
    var connection = Configuration.GetSection("SqlConnection1").Value;
    services.AddScoped<IDharma, DharmaRepo>();
    services.AddDbContext<DharmaContext>(options => options.UseSqlServer(connection));
  }

The code in DharmaContext (I removed most of the data columns to make it shorter): DharmaContext 中的代码(我删除了大部分数据列以使其更短):

 public partial class DharmaContext : DbContext
 {
    public DharmaContext()
    {
    }

    public DharmaContext(DbContextOptions<DharmaContext> options)
        : base(options)
    {
    }

    public virtual DbSet<NewBusinessMaster> NewBusinessMaster { get; set; }
    public virtual DbSet<NewBusinessDetail> NewBusinessDetail { get; set; }


    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");
        modelBuilder.Entity<NewBusinessMaster>(entity =>
        {
            entity.HasKey(e => e.NbTransactionId);

            entity.ToTable("NewBusiness_Master");

            entity.Property(e => e.NbTransactionId).HasColumnName("NB_TRANSACTION_ID");

            entity.Property(e => e.NbLob)
                .HasColumnName("NB_LOB")
                .HasMaxLength(2)
                .IsUnicode(false);

        });

        modelBuilder.Entity<NewBusinessDetail>(entity =>
        {
            entity.HasKey(e => e.NbTransactionId);

            entity.ToTable("NewBusiness_Detail");

            entity.Property(e => e.NbTransactionId).HasColumnName("NB_TRANSACTION_ID");
        });
            entity.Property(e => e.NbAgentNumber)
                .IsRequired()
                .HasColumnName("NB_AGENT_NUMBER")
                .HasMaxLength(9)
                .IsUnicode(false);
     }
  }

The models (I removed most of the data coumns to make it easier to read):模型(我删除了大部分数据以使其更易于阅读):

    public partial class NewBusinessMaster
    {
        public int NbTransactionId { get; set; }
        public string NbLob { get; set; }

        public List<NewBusinessDetail> NewBusinessDetail { get; set; }

        public NewBusinessMaster()
        {
            NewBusinessDetail = new List<NewBusinessDetail>();
        }

    }

    public partial class NewBusinessDetail
    {
        public int NbTransactionId { get; set; }
        public string NbAgentNumber { get; set; }
    }
}

The code to add and save records:添加和保存记录的代码:

NewBusinessMaster nbMaster = new NewBusinessMaster();
nbMaster.NbLob = "AU";
NewBusinessDetail nbDetailItem = new NewBusinessDetail();
foreach (XElement item in screenH202.Descendants())
{
    nbDetailItem = new NewBusinessDetail();
    if (!string.IsNullOrEmpty(item.Value))
    {
        nbDetailItem.NbAgentNumber = nbMaster.NbAgentNumber;
    }
}
_context.NewBusinessMaster.Add(nbMaster);
 try
 {
    await _context.SaveChangesAsync(); //this line throws the error
 }
 catch (DbUpdateException dbEx)
 {
    throw;
 }

Screenshots of the SQL: SQL截图:

在此处输入图像描述

在此处输入图像描述

By definition, an "entity" is an object with an identifier.根据定义,“实体”是带有标识符的 object。 It's called Entity Framework for a reason, it's a framework for working with entities, which means they must have primary keys (the identifier).它被称为实体框架是有原因的,它是一个用于处理实体的框架,这意味着它们必须具有主键(标识符)。

That said, there might be a couple of options for you here.也就是说,这里可能有几个选项供您选择。 First, EF Core supports what it calls " owned entities ".首先,EF Core 支持它所谓的“自有实体”。 These are essentially value objects (an object that acquires its identity from the sum of its values, rather than an explicit identifier, such as an address), and as such, do not have explicit identifier properties.这些本质上是值对象(一个 object 从其值的总和而不是显式标识符(例如地址)中获取其身份),因此没有显式标识符属性。 However, they still have a primary key, which is just the foreign key, setting up a one-to-one relationship with the entity that "owns" them.但是,它们仍然有一个主键,也就是外键,与“拥有”它们的实体建立了一对一的关系。 I'm not sure how you would actually scaffold an owned type, though.不过,我不确定您将如何实际构建自有类型。 If you have a table where a foreign key is also a primary key, EF Core may extrapolate that it's an owned type from that, but that may still require adding a primary key to the table, if this is not already the case.如果您有一个表,其中外键也是主键,EF Core 可能会推断它是一个拥有的类型,但如果还不是这种情况,则可能仍需要向表中添加主键。

The only other option is what EF Core refers to as query types or keyless entity types (the name has changed in 3.0 to keyless).唯一的其他选项是 EF Core 所指的查询类型或无键实体类型(名称在 3.0 中已更改为无键)。 These are very literally tables or views without a primary key or simply the results from something like a function or stored procedure, matching your scenario here pretty much exactly.这些实际上是没有主键的表或视图,或者只是来自 function 或存储过程之类的结果,与您的场景非常匹配。 However, they can only be read, not inserted or modified, which may not work for your scenario.但是,它们只能读取,不能插入或修改,这可能不适用于您的方案。 I'm also not sure how this would be managed with scaffolding.我也不确定如何使用脚手架进行管理。 Keyless types are more something you'd manually add to your context, not something EF Core would ever generate for you.无键类型更多是您手动添加到上下文中的东西,而不是 EF Core 会为您生成的东西。

I was finally given permission to add a key to the child table.我终于被允许向子表添加一个键。 That made the code simple and I could use the scaffold command.这使代码变得简单,我可以使用脚手架命令。

The classes:课程:

public partial class NewBusinessMaster
{
    public NewBusinessMaster()
    {
        NewBusinessDetail = new HashSet<NewBusinessDetail>();
    }

    public int NbTransactionId { get; set; }
    public string NbLob { get; set; }
    public string NbReferenceNumber { get; set; }
    public string NbAgentNumber { get; set; }
    public string NbEntryOper { get; set; }
    public string NbEffectiveDate { get; set; }
    public string NbInsName { get; set; }
    public string NbInsNameAddr { get; set; }
    public string NbInsAddr { get; set; }
    public string NbInsCity { get; set; }
    public string NbInsState { get; set; }
    public string NbInsZip { get; set; }
    public string NbInsPhone { get; set; }
    public string NbUploadInd { get; set; }
    public DateTime NbCreateDate { get; set; }
    public string NbLockedBy { get; set; }
    public string NbQuoteId { get; set; }

    public virtual ICollection<NewBusinessDetail> NewBusinessDetail { get; set; }
}


public partial class NewBusinessDetail
{
    public int NewBusinessDetailId { get; set; }
    public int NbTransactionId { get; set; }
    public string NbAgentNumber { get; set; }
    public string NbScreenName { get; set; }
    public string NbFieldName { get; set; }
    public string NbFieldValue { get; set; }
    public DateTime? NbLastUpdated { get; set; }

    public virtual NewBusinessMaster NbTransaction { get; set; }
}

//Context
public partial class DharmaContext : DbContext
{
    public DharmaContext()
    {
    }

    public DharmaContext(DbContextOptions<DharmaContext> options)
        : base(options)
    {
    }

    public virtual DbSet<NewBusinessDetail> NewBusinessDetail { get; set; }
    public virtual DbSet<NewBusinessMaster> NewBusinessMaster { get; set; }


    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {

    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasAnnotation("ProductVersion", "2.2.4-servicing-10062");

        modelBuilder.Entity<NewBusinessDetail>(entity =>
        {
            entity.Property(e => e.NewBusinessDetailId).HasColumnName("NewBusinessDetail_ID");

            entity.Property(e => e.NbAgentNumber)
                .IsRequired()
                .HasColumnName("NB_AGENT_NUMBER")
                .HasMaxLength(9)
                .IsUnicode(false);

            entity.Property(e => e.NbFieldName)
                .HasColumnName("NB_FIELD_NAME")
                .HasMaxLength(8)
                .IsUnicode(false);

            entity.Property(e => e.NbFieldValue)
                .HasColumnName("NB_FIELD_VALUE")
                .HasMaxLength(1000)
                .IsUnicode(false);

            entity.Property(e => e.NbLastUpdated)
                .HasColumnName("NB_LAST_UPDATED")
                .HasColumnType("datetime")
                .HasDefaultValueSql("(getdate())");

            entity.Property(e => e.NbScreenName)
                .HasColumnName("NB_SCREEN_NAME")
                .HasMaxLength(4)
                .IsUnicode(false);

            entity.Property(e => e.NbTransactionId).HasColumnName("NB_TRANSACTION_ID");

            entity.HasOne(d => d.NbTransaction)
                .WithMany(p => p.NewBusinessDetail)
                .HasForeignKey(d => d.NbTransactionId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("MasterDetail_FK");
        });

        modelBuilder.Entity<NewBusinessMaster>(entity =>
        {
            entity.HasKey(e => e.NbTransactionId);

            entity.Property(e => e.NbTransactionId).HasColumnName("NB_TRANSACTION_ID");

            entity.Property(e => e.NbAgentNumber)
                .IsRequired()
                .HasColumnName("NB_AGENT_NUMBER")
                .HasMaxLength(9)
                .IsUnicode(false);

            entity.Property(e => e.NbCreateDate)
                .HasColumnName("NB_CREATE_DATE")
                .HasColumnType("datetime")
                .HasDefaultValueSql("(getdate())");

            entity.Property(e => e.NbEffectiveDate)
                .HasColumnName("NB_EFFECTIVE_DATE")
                .HasMaxLength(6)
                .IsUnicode(false);

            entity.Property(e => e.NbEntryOper)
                .IsRequired()
                .HasColumnName("NB_ENTRY_OPER")
                .HasMaxLength(3)
                .IsUnicode(false);

            entity.Property(e => e.NbInsAddr)
                .HasColumnName("NB_INS_ADDR")
                .HasMaxLength(30)
                .IsUnicode(false);

            entity.Property(e => e.NbInsCity)
                .HasColumnName("NB_INS_CITY")
                .HasMaxLength(30)
                .IsUnicode(false);

            entity.Property(e => e.NbInsName)
                .HasColumnName("NB_INS_NAME")
                .HasMaxLength(30)
                .IsUnicode(false);

            entity.Property(e => e.NbInsNameAddr)
                .HasColumnName("NB_INS_NAME_ADDR")
                .HasMaxLength(30)
                .IsUnicode(false);

            entity.Property(e => e.NbInsPhone)
                .HasColumnName("NB_INS_PHONE")
                .HasMaxLength(12)
                .IsUnicode(false);

            entity.Property(e => e.NbInsState)
                .HasColumnName("NB_INS_STATE")
                .HasMaxLength(2)
                .IsUnicode(false);

            entity.Property(e => e.NbInsZip)
                .HasColumnName("NB_INS_ZIP")
                .HasMaxLength(11)
                .IsUnicode(false);

            entity.Property(e => e.NbLob)
                .HasColumnName("NB_LOB")
                .HasMaxLength(2)
                .IsUnicode(false);

            entity.Property(e => e.NbLockedBy)
                .HasColumnName("NB_LOCKED_BY")
                .HasMaxLength(3)
                .IsUnicode(false);

            entity.Property(e => e.NbQuoteId)
                .HasColumnName("NB_QUOTE_ID")
                .HasMaxLength(15)
                .IsUnicode(false);

            entity.Property(e => e.NbReferenceNumber)
                .IsRequired()
                .HasColumnName("NB_REFERENCE_NUMBER")
                .HasMaxLength(9)
                .IsUnicode(false);

            entity.Property(e => e.NbUploadInd)
                .HasColumnName("NB_UPLOAD_IND")
                .HasMaxLength(1)
                .IsUnicode(false);
        });
    }


//Code to add parent and child
NewBusinessMaster nbMaster = new NewBusinessMaster();
//set each property of master
//...

nbDetailItem = new NewBusinessDetail();
nbMaster.NewBusinessDetail.Add(nbDetailItem);
_context.NewBusinessMaster.Add(nbMaster);
 try
        {
            await _context.SaveChangesAsync();

        }
        catch (DbUpdateException dbEx)
        {

            throw;
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM