我正在使用 this 项目作为我的 web API 的模板。我已经用它们的主键和外键创建了表,并用数据填充了它们。当我尝试将数据添加到数据库中的另一个新表时,由于某种我无法理解的原因,框架忽略了自动索引属性“Id”。此错误导致自动生成的 SQL 语句执行失败,因为没有提供 ID 索引,假设它不是空属性。新数据未添加到表中,尽管之前对其他表的数据更新已成功完成。
表的实体类实现了一个接口和一个对象
public interface IAggregateRoot
{
}
public abstract class BaseEntity<T>
{
public virtual int Id { get; protected set; }
}
只有“Id”作为属性。
在这里你可以看到课程,
public class Shop_Empleado : BaseEntity<Shop_Empleado>, IAggregateRoot
{
public long Ruc { get; set; }
public string Nombre1 { get; set; }
public string Nombre2 { get; set; }
public string Apellido1 { get; set; }
public string Apellido2 { get;set; }
public int Edad { get; set; }
public string Direccion1 { get; set; }
public string Direccion2 { get; set; }
public string Nacionalidad { get; set; }
public string Telefono1 { get; set; }
public string Telefono2 { get; set;}
public string Email { get; set; }
public string Puesto { get; set; }
public Shop_Local? Shop_Local { get; set; }
public int LocalId { get; set; }
public double Salario { get; set; }
//public DateTime Fecha_Ingreso { get; set; }
public bool Iess { get; set; }
public Shop_Empleado(long Ruc, string Nombre1, string Nombre2, string Apellido1, string Apellido2,
int Edad, string Direccion1, string Direccion2, string Nacionalidad, string Telefono1,
string Puesto, double Salario, bool Iess, string Telefono2 = "-",
string Email = "-", int LocalId = 1)
{
this.Ruc = Ruc;
this.Nombre1 = Nombre1;
this.Nombre2 = Nombre2;
this.Apellido1 = Apellido1;
this.Apellido2 = Apellido2;
this.Edad = Edad;
this.Direccion1 = Direccion1;
this.Direccion2 = Direccion2;
this.Nacionalidad = Nacionalidad;
this.Telefono1 = Telefono1;
this.Telefono2 = Telefono2;
this.Email = Email;
this.Puesto = Puesto;
this.Salario = Salario;
//this.Fecha_Ingreso = Fecha_Ingreso;
this.Iess = Iess;
this.LocalId = LocalId;
}
配置,
public class Shop_Empleado_Configurations : IEntityTypeConfiguration<Shop_Empleado>
{
public void Configure(EntityTypeBuilder<Shop_Empleado> builder)
{
builder.ToTable("Shop_Empleado");
builder.Property(ai => ai.Id)
.UseHiLo("shop_empleado_hilo")
.IsRequired();
builder.Property(ai => ai.Ruc)
.IsRequired(true)
.HasColumnType("bigint");
builder.Property(ai => ai.Nombre1)
.IsRequired(true)
.HasMaxLength(25);
builder.Property(ai => ai.Nombre2)
.IsRequired(true)
.HasMaxLength(25);
builder.Property(ai => ai.Apellido1)
.IsRequired(true)
.HasMaxLength(25);
builder.Property(ai => ai.Apellido2)
.IsRequired(true)
.HasMaxLength(25);
builder.Property(ai => ai.Edad)
.IsRequired(true)
.HasColumnType("integer");
builder.Property(ai => ai.Direccion1)
.IsRequired(true)
.HasMaxLength(90);
builder.Property(ai => ai.Direccion2)
.IsRequired(true)
.HasMaxLength(90);
builder.Property(ai => ai.Nacionalidad)
.IsRequired(true)
.HasMaxLength(30);
builder.Property(ai => ai.Telefono1)
.IsRequired(true)
.HasMaxLength(12);
builder.Property(ai => ai.Telefono2)
.IsRequired(false)
.HasMaxLength(12);
builder.Property(ai => ai.Email)
.IsRequired(false)
.HasMaxLength(100);
builder.Property(ai => ai.Puesto)
.IsRequired(true)
.HasMaxLength(35);
builder.HasOne(ai => ai.Shop_Local)
.WithMany()
.HasPrincipalKey(ci => ci.Id)
.IsRequired(true);
builder.Property(ai => ai.Salario)
.IsRequired (true)
.HasColumnType ("decimal(6,2)");
//builder.Property(ai => ai.Fecha_Ingreso)
// .IsRequired (true)
// .HasColumnType ("datetime2(7)");
builder.Property(ai => ai.Iess)
.IsRequired(true)
.HasColumnType("bit");
}
和 InitialModel
protected override void Up(MigrationBuilder migrationBuilder)
{
//Creacion Tabla Empleado
migrationBuilder.CreateSequence(
name: "shop_empleado_hilo",
incrementBy: 10);
migrationBuilder.CreateTable(
name: "Shop_Empleado",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false),
Ruc = table.Column<long>(type: "bigint", maxLength: 13, nullable: false),
Nombre1 = table.Column<string>(type: "nvarchar(25)", maxLength: 35, nullable: false),
Nombre2 = table.Column<string>(type: "nvarchar(25)", maxLength: 35, nullable: false),
Apellido1 = table.Column<string>(type: "nvarchar(25)", maxLength: 35, nullable: false),
Apellido2 = table.Column<string>(type: "nvarchar(25)", maxLength: 35, nullable: false),
Edad = table.Column<int>(type: "int", nullable: false),
Direccion1 = table.Column<string>(type: "nvarchar(90)", maxLength: 90, nullable: false),
Direccion2 = table.Column<string>(type: "nvarchar(90)", maxLength: 90, nullable: false),
Nacionalidad = table.Column<int>(type: "nvarchar(30)", maxLength: 30, nullable: false),
Telefono1 = table.Column<string>(type: "nvarchar(12)", maxLength: 12, nullable: false),
Telefono2 = table.Column<string>(type: "nvarchar(12)", maxLength: 12, nullable: true),
Email = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Puesto = table.Column<string>(type: "nvarchar(35)", maxLength: 35, nullable: false),
LocalId = table.Column<int>(type: "int", nullable: false),
Salario = table.Column<double>(type: "decimal(6,2)", nullable: false),
//Fecha_Ingreso = table.Column<DateTime>(type: "datetime2(7)", maxLength: 7, nullable: false),
Iess = table.Column<bool>(type: "bit", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Shop_Empleado", x => x.Id);
//table.ForeignKey("FK_Shop_Local_Shop_LocalId",
// column: x => x.LocalId,
// principalTable: "Shop_Local",
// principalColumn: "Id",
// onDelete: ReferentialAction.Cascade);
});
}
创建数据库表和配置实体的文件。文件模板已成功用于其他表和对象。对于这个特定实体,自动生成的 SQL 会忽略 ID 属性。
错误提示:
SELECT CASE
WHEN EXISTS (
SELECT 1
FROM [Shop_Empleado] AS [s]) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END
Microsoft.EntityFrameworkCore.Database.Command: Information: Executed DbCommand (7ms) [Parameters=[@p0='?' (Size = 25), @p1='?' (Size = 25), @p2='?' (Size = 90), @p3='?' (Size = 90), @p4='?' (DbType = Int32), @p5='?' (Size = 100), @p6='?' (DbType = Boolean), @p7='?' (DbType = Int32), @p8='?' (Size = 30), @p9='?' (Size = 25), @p10='?' (Size = 25), @p11='?' (Size = 35), @p12='?' (DbType = Int64), @p13='?' (Precision = 6) (Scale = 2) (DbType = Decimal), @p14='?' (Size = 12), @p15='?' (Size = 12), @p16='?' (Size = 25), @p17='?' (Size = 25), @p18='?' (Size = 90), @p19='?' (Size = 90), @p20='?' (DbType = Int32), @p21='?' (Size = 100), @p22='?' (DbType = Boolean), @p23='?' (DbType = Int32), @p24='?' (Size = 30), @p25='?' (Size = 25), @p26='?' (Size = 25), @p27='?' (Size = 35), @p28='?' (DbType = Int64), @p29='?' (Precision = 6) (Scale = 2) (DbType = Decimal), @p30='?' (Size = 12), @p31='?' (Size = 12), @p32='?' (Size = 25), @p33='?' (Size = 25), @p34='?' (Size = 90), @p35='?' (Size = 90), @p36='?' (DbType = Int32), @p37='?' (Size = 100), @p38='?' (DbType = Boolean), @p39='?' (DbType = Int32), @p40='?' (Size = 30), @p41='?' (Size = 25), @p42='?' (Size = 25), @p43='?' (Size = 35), @p44='?' (DbType = Int64), @p45='?' (Precision = 6) (Scale = 2) (DbType = Decimal), @p46='?' (Size = 12), @p47='?' (Size = 12)], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
MERGE [Shop_Empleado] USING (
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, 0),
(@p16, @p17, @p18, @p19, @p20, @p21, @p22, @p23, @p24, @p25, @p26, @p27, @p28, @p29, @p30, @p31, 1),
(@p32, @p33, @p34, @p35, @p36, @p37, @p38, @p39, @p40, @p41, @p42, @p43, @p44, @p45, @p46, @p47, 2)) AS i ([Apellido1], [Apellido2], [Direccion1], [Direccion2], [Edad], [Email], [Iess], [LocalId], [Nacionalidad], [Nombre1], [Nombre2], [Puesto], [Ruc], [Salario], [Telefono1], [Telefono2], _Position) ON 1=0
WHEN NOT MATCHED THEN
INSERT ([Apellido1], [Apellido2], [Direccion1], [Direccion2], [Edad], [Email], [Iess], [LocalId], [Nacionalidad], [Nombre1], [Nombre2], [Puesto], [Ruc], [Salario], [Telefono1], [Telefono2])
VALUES (i.[Apellido1], i.[Apellido2], i.[Direccion1], i.[Direccion2], i.[Edad], i.[Email], i.[Iess], i.[LocalId], i.[Nacionalidad], i.[Nombre1], i.[Nombre2], i.[Puesto], i.[Ruc], i.[Salario], i.[Telefono1], i.[Telefono2])
OUTPUT INSERTED.[Id], i._Position;
'iisexpress.exe' (CoreCLR: clrhost): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.3\System.Reflection.Metadata.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Microsoft.EntityFrameworkCore.Update: Error: An exception occurred in the database while saving changes for context type 'Infrastructure.Data.Shop_Context'.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'Id', table 'SagaMotors_API.CatalogDb.dbo.Shop_Empleado'; column does not allow nulls. UPDATE fails.
at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at Microsoft.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
at Microsoft.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
at Microsoft.Data.SqlClient.SqlDataReader.ReadAsyncExecute(Task task, Object state)
at Microsoft.Data.SqlClient.SqlDataReader.InvokeAsyncCall[T](SqlDataReaderAsyncCallContext`1 context)
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetAsync(Int32 startCommandIndex, RelationalDataReader reader, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
ClientConnectionId:0b3a38fc-9621-4ae5-8cda-5cbef60dd43c
Error Number:515,State:2,Class:16
我对 C# 和 .NET 并不陌生,也不是专业人士。有人可以帮我解决这个恼人的问题吗?
我尝试使用显示的文件模板,因为它们成功地创建并向表实体添加了数据。我希望框架自动生成与其他情况相同的 SQL 语句,但它忽略了“ID”属性。该错误指出 ID 不能为 null,但在声明中从未给出 ID 的值。
另外,我不知道为什么 SQL 语句在应该自动索引该属性时尝试输出插入的 ID。正如您在促销中看到的那样,SQL 从未在语句中为 ID 提供任何值。
所以,经过八个小时的良好休息并仔细阅读代码后,我发现问题出在我的表引用的外键上。问题的核心在于配置文件中是否配置了类型、键和数据要求。正如您在给定代码中看到的那样,我错误地尝试在“LocalId”中设置主键,因为我必须使用外键。此错误使 .NET Core 在插入数据时尝试使用 Merge Sql 操作。此外,编码中的错误使 .NET 忽略了打算作为默认索引和主键的 ID 属性。正确的代码是:
builder.HasOne(ai => ai.Shop_Local)
.WithMany()
.HasForeignKey(ci => ci.LocalId)
.IsRequired(true);
请注意,使用方法“HasForeingKey()”代替“HasPrimaryKey()”,并且实体类的成员“LocalId”正在替换“Id”成员。