我已经创建了一个完整的 EF 挂钩到我们的一个数据库(我不控制其结构)来执行一些基本的 CRUD 操作。到目前为止,一切都很顺利。但是,我在插入我的一门课程时遇到了问题。它正在尝试将新记录插入名为“applmort”的表中。我不会过多介绍该数据库表的设计方式,因为创建它的不是我的公司。但我们可以访问它并且可以对其进行 CRUD 操作。
该表有一列我称之为
UWT
,它被声明为 varchar(12)
。因此,我设置了 EF 配置,将输入的值限制为 12。您会在我将发布的“配置”文件中注意到这一点。虽然该列是 NOTNULL
,但我可以简单地在该列中放入一个空白 varchar
,一切都很好。对此没有表限制。
因此,当我尝试添加新记录时,我没有在对象中指定此字段。我可以使用表中的一堆其他列来执行此操作,并且由于我的配置文件告诉 EF 插入一个 string.Empty 作为默认值,所以一切都很顺利。除了这个
UWT
专栏。它犹豫不决并告诉我存在截断错误。由于我放入了一个空字符串,这看起来很奇怪。我深入研究并意识到 EF 正在尝试创建此 UWT
列作为备用键,然后用我从未告诉过它使用的随机 GUID 填充它。我追踪到这一点,发现我有另一个表通过配置文件连接到这个表(应该是我在下面列出的第二个配置类)。这个另一个对象通过 UWT
链接到我的应用程序对象。这应该是正常的,我不认为把它放进去会引起问题。然而,确实如此。当我从第二个对象中删除“一对多”以断开链接时,记录会正确插入。
我发现的另一个解决方法是在应用程序对象上的
UWT
列指定为空白字符串,然后再达到配置中的默认值。这也允许毫无问题地插入记录。
我可以使用这些解决方法中的任何一个。第二个效果最好,可以让我保留我的表格链接。但这看起来非常非常奇怪。我创建的任何其他表链接都不会发生这种情况,所以我必须问:我在这里做错了什么吗?我是否在某处设置了一些导致 GUID 被推入非常明显的非 GUID 列的内容?我一生都找不到这个。
public class Application
{
public DateTime? ChangeDate { get; set; }
public int ID { get; set; }
public DateTime? ApplicationDate { get; set; }
public string StructureID { get; set; } = null!;
public string UWT { get; set; } = null!;
public int UnitNumber { get; set; }
public virtual Structure Structure { get; set; } = null!;
public virtual ICollection<ApplicationHold> ApplicationHolds { get; set; } = [];
}
public class ApplicationHold
{
public DateTime? ChangeDate { get; set; }
public string UWT { get; set; } = null!;
public int ID { get; set; }
public virtual Application Application { get; set; } = null!;
}
public class ApplicationConfig : IEntityTypeConfiguration<Application>
{
public void Configure(EntityTypeBuilder<Application> entity)
{
entity.ToTable("applmort");
entity.HasKey(e => e.ID);
entity.Property(e => e.ChangeDate)
.HasColumnName("changedate")
.HasColumnType("datetime")
.HasDefaultValue(DateTime.Now)
.IsRequired();
entity.Property(e => e.ID)
.HasColumnName("id")
.UseIdentityColumn();
entity.Property(e => e.ApplicationDate)
.HasColumnName("appldate")
.HasColumnType("datetime")
.HasDefaultValue(DateTime.Now);
entity.Property(e => e.StructureID)
.HasColumnName("stru")
.HasMaxLength(3)
.HasDefaultValue(string.Empty)
.IsRequired();
entity.Property(e => e.UWT)
.HasColumnName("uwt")
.HasColumnType("varchar")
.HasMaxLength(12)
.HasDefaultValue(string.Empty)
.IsRequired();
entity.Property(e => e.UnitNumber)
.HasColumnName("units")
.HasColumnType("int")
.HasDefaultValue(0)
.IsRequired();
entity.HasOne(e => e.Structure).WithMany(e => e.Applications)
.HasForeignKey(e => e.LoanStructureID)
.HasPrincipalKey(e => e.LoanStructureID)
.IsRequired(false)
.OnDelete(DeleteBehavior.NoAction);
}
}
public class ApplicationHoldConfig : IEntityTypeConfiguration<ApplicationHold>
{
public void Configure(EntityTypeBuilder<ApplicationHold> entity)
{
entity.ToTable("applhold");
entity.HasKey(e => e.ID);
entity.Property(e => e.ChangeDate)
.HasColumnName("changedate")
.HasColumnType("datetime")
.HasDefaultValue(DateTime.Now)
.IsRequired();
entity.Property(e => e.ID)
.HasColumnName("id")
.UseIdentityColumn();
entity.Property(e => e.UWT)
.HasColumnName("uwt")
.HasColumnType("varchar")
.HasMaxLength(12)
.HasDefaultValue(string.Empty)
.IsRequired();
entity.HasOne(entity => entity.Application).WithMany(e => e.ApplicationHolds)
.HasForeignKey(entity => entity.UWT)
.HasPrincipalKey(e => e.UWT)
.IsRequired(false)
.OnDelete(DeleteBehavior.NoAction);
}
}
EF 试图通过它如何理解 Application 和 ApplicationHold 之间的关系来对 UWT 字段进行唯一约束
您可以尝试不使用 HasDefaultValue(string.Empty),因为似乎即使拥有此代码也足以使 EF 自动生成关系,并删除默认值配置并在您的应用程序中处理它们。
entity.Property(e => e.UWT)
.HasColumnName("uwt")
.HasColumnType("varchar")
.HasMaxLength(12)
.HasDefaultValue(string.Empty)
.IsRequired();
直接设置此值应该可以解决插入记录时的问题
Application application = new()
{
UWT = string.Empty,
};