我有一个父子关系,并且我无法在EF Core中使用脚手架命令,因为子表没有键。我不允许添加密钥,所以我被体系结构所困扰。
保存更改时,出现以下内部异常: 无效的列名“ NewBusinessMasterNbTransactionId”
Startup.cs中的代码:
public void ConfigureServices(IServiceCollection services)
{
var connection = Configuration.GetSection("SqlConnection1").Value;
services.AddScoped<IDharma, DharmaRepo>();
services.AddDbContext<DharmaContext>(options => options.UseSqlServer(connection));
}
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);
}
}
模型(我删除了大多数数据列以使其更易于阅读):
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; }
}
}
添加和保存记录的代码:
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;
}
SQL的屏幕截图:
答案 0 :(得分:0)
根据定义,“实体”是带有标识符的对象。出于某种原因,它称为 Entity 框架,它是用于处理实体的框架,这意味着它们必须具有主键(标识符)。
也就是说,这里可能有几个选项供您选择。首先,EF Core支持所谓的“ owned entities”。这些本质上是值对象(从其值的总和中获取其身份的对象,而不是诸如地址之类的显式标识符),因此不具有显式标识符属性。但是,它们仍然具有主键,即外键,与“拥有”它们的实体建立一对一关系。不过,我不确定您将如何实际搭建一个自有类型。如果您有一个表,其中外键也是主键,则EF Core可能会推断出它是该表的拥有类型,但是如果情况并非如此,仍可能需要在表中添加主键。>
唯一的选择是EF Core称为查询类型或keyless entity types(名称在3.0中已更改为无键)。这些实际上是没有主键的表或视图,或者仅仅是函数或存储过程之类的结果,几乎完全符合您的方案。但是,只能读取它们,不能插入或修改它们,这可能不适用于您的方案。我也不确定如何使用脚手架进行管理。无键类型更多是您要手动添加到上下文中的内容,而不是EF Core会为您生成的内容。
答案 1 :(得分:0)
我终于获得了将键添加到子表的权限。这样可以简化代码,我可以使用scaffold命令。
课程:
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;
}