Postgres GENERATED AS IDENTITY 与 .NET 实体模型冲突
Postgres GENERATED AS IDENTITY conflicted with .NET Entity Model
我正在构建并 API 使用 .NET Core、PostgresSQL 和 SQLKata+dapper(非 EF)
我有这 2 tables
CREATE TABLE "UserProfile"(
"Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
"Deleted" BOOLEAN NOT NULL DEFAULT FALSE,
"CreatedBy" VARCHAR(50) NOT NULL,
"CreatedTime" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_DATE,
"LastModifiedBy" VARCHAR(50),
"LastModifiedTime" TIMESTAMP WITH TIME ZONE,
"FirstName" VARCHAR(50) NOT NULL,
"LastName" VARCHAR(50),
"Email" VARCHAR(50) UNIQUE NOT NULL
);
CREATE TABLE "UserLogin"(
"Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
"Deleted" BOOLEAN NOT NULL DEFAULT FALSE,
"CreatedBy" VARCHAR(50) NOT NULL,
"CreatedTime" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_DATE,
"LastModifiedBy" VARCHAR(50),
"LastModifiedTime" TIMESTAMP WITH TIME ZONE,
"Username" VARCHAR(50) UNIQUE NOT NULL,
"Password" VARCHAR(200) NOT NULL,
"IsLocked" BOOLEAN NOT NULL DEFAULT FALSE,
"IsActive" BOOLEAN NOT NULL DEFAULT FALSE,
"UserProfileId" INT NOT NULL,
CONSTRAINT "FK_UserLogin_UserProfile" FOREIGN KEY("UserProfileId") REFERENCES "UserProfile"("Id")
);
在我的 C# 中,我创建了包含 table
的实体
public class BaseEntity
{
public int Id { set; get; }
public bool Deleted { set; get; }
public string CreatedBy { set; get; }
public DateTime CreatedTime { set; get; }
public string LastModifiedBy { set; get; }
public DateTime? LastModifiedTime { set; get; }
public BaseEntity()
{
this.Deleted = false;
this.CreatedBy = "SYSTEM"; //TODO: Change to UserPrincipal
this.CreatedTime = DateTime.Now;
this.LastModifiedBy = null;
this.LastModifiedTime = null;
}
}
public class UserLogin : BaseEntity
{
public string Username { set; get; }
public string Password { set; get; }
public bool IsLocked { set; get; }
public bool IsActive { set; get; }
public int UserProfileId { set; get; }
}
public class UserProfile:BaseEntity
{
public string FirstName { set; get; }
public string LastName { set; get; }
public string Email { set; get; }
}
那么问题来了,如果我要插入新记录到数据库
public async Task<ResponseBase> SignUp(SignUpRequest request)
{
ResponseBase result = new ResponseBase();
try
{
using var conn = await db.CreateConnectionAsync();
var query = new QueryFactory(conn, new PostgresCompiler());
var scope = conn.BeginTransaction();
var userProfileId = await query.Query(UserProfileConst.TableName)
.InsertAsync(new UserProfile
{
FirstName = request.FirstName,
LastName = request.LastName,
Email = request.Email
});
var affectedUserLogin = await query.Query(UserLoginConst.TableName)
.InsertAsync(new UserLogin
{
Username = request.Username,
Password = Argon2.Hash(request.Password),
IsActive = true,
IsLocked = false,
UserProfileId = userProfileId
});
if (userProfileId > 0 && affectedUserLogin > 0)
{
scope.Commit();
result.Success("Success Insert New User");
}
else
{
scope.Rollback();
result.Failed("Success Insert New User");
}
}
catch (Exception e)
{
result.Failed(e.Message);
}
return result;
}
new UserLogin({ })
和 new UserProfile({ })
会自动将默认值设置为 Id
从 BaseEntity
到 0
并且会在 Postgres
中导致错误
{
"acknowledge": 0,
"message": "428C9: cannot insert into column \"Id\"",
"isSuccess": false
}
我知道我可以创建新的 Object
而无需定义它的 class,但我想知道是否还有其他方法
有人知道吗?
您可以在列上使用 KeyAttribute
注释将其标记为主键,以便在 Insert/Update 查询时忽略它。
您也可以使用 Ignore
属性来忽略任意字段
public class BaseEntity
{
[Key]
public int PrimaryKeyColumnWillBeIgnoredOnInsert { set; get; }
[Ignore]
public int ThisColumnWillBeIgnoredAlso { set; get; }
}
检查
https://github.com/sqlkata/querybuilder/blob/master/QueryBuilder/ColumnAttribute.cs#L27
我正在构建并 API 使用 .NET Core、PostgresSQL 和 SQLKata+dapper(非 EF)
我有这 2 tables
CREATE TABLE "UserProfile"(
"Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
"Deleted" BOOLEAN NOT NULL DEFAULT FALSE,
"CreatedBy" VARCHAR(50) NOT NULL,
"CreatedTime" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_DATE,
"LastModifiedBy" VARCHAR(50),
"LastModifiedTime" TIMESTAMP WITH TIME ZONE,
"FirstName" VARCHAR(50) NOT NULL,
"LastName" VARCHAR(50),
"Email" VARCHAR(50) UNIQUE NOT NULL
);
CREATE TABLE "UserLogin"(
"Id" INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
"Deleted" BOOLEAN NOT NULL DEFAULT FALSE,
"CreatedBy" VARCHAR(50) NOT NULL,
"CreatedTime" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_DATE,
"LastModifiedBy" VARCHAR(50),
"LastModifiedTime" TIMESTAMP WITH TIME ZONE,
"Username" VARCHAR(50) UNIQUE NOT NULL,
"Password" VARCHAR(200) NOT NULL,
"IsLocked" BOOLEAN NOT NULL DEFAULT FALSE,
"IsActive" BOOLEAN NOT NULL DEFAULT FALSE,
"UserProfileId" INT NOT NULL,
CONSTRAINT "FK_UserLogin_UserProfile" FOREIGN KEY("UserProfileId") REFERENCES "UserProfile"("Id")
);
在我的 C# 中,我创建了包含 table
的实体public class BaseEntity
{
public int Id { set; get; }
public bool Deleted { set; get; }
public string CreatedBy { set; get; }
public DateTime CreatedTime { set; get; }
public string LastModifiedBy { set; get; }
public DateTime? LastModifiedTime { set; get; }
public BaseEntity()
{
this.Deleted = false;
this.CreatedBy = "SYSTEM"; //TODO: Change to UserPrincipal
this.CreatedTime = DateTime.Now;
this.LastModifiedBy = null;
this.LastModifiedTime = null;
}
}
public class UserLogin : BaseEntity
{
public string Username { set; get; }
public string Password { set; get; }
public bool IsLocked { set; get; }
public bool IsActive { set; get; }
public int UserProfileId { set; get; }
}
public class UserProfile:BaseEntity
{
public string FirstName { set; get; }
public string LastName { set; get; }
public string Email { set; get; }
}
那么问题来了,如果我要插入新记录到数据库
public async Task<ResponseBase> SignUp(SignUpRequest request)
{
ResponseBase result = new ResponseBase();
try
{
using var conn = await db.CreateConnectionAsync();
var query = new QueryFactory(conn, new PostgresCompiler());
var scope = conn.BeginTransaction();
var userProfileId = await query.Query(UserProfileConst.TableName)
.InsertAsync(new UserProfile
{
FirstName = request.FirstName,
LastName = request.LastName,
Email = request.Email
});
var affectedUserLogin = await query.Query(UserLoginConst.TableName)
.InsertAsync(new UserLogin
{
Username = request.Username,
Password = Argon2.Hash(request.Password),
IsActive = true,
IsLocked = false,
UserProfileId = userProfileId
});
if (userProfileId > 0 && affectedUserLogin > 0)
{
scope.Commit();
result.Success("Success Insert New User");
}
else
{
scope.Rollback();
result.Failed("Success Insert New User");
}
}
catch (Exception e)
{
result.Failed(e.Message);
}
return result;
}
new UserLogin({ })
和 new UserProfile({ })
会自动将默认值设置为 Id
从 BaseEntity
到 0
并且会在 Postgres
{
"acknowledge": 0,
"message": "428C9: cannot insert into column \"Id\"",
"isSuccess": false
}
我知道我可以创建新的 Object
而无需定义它的 class,但我想知道是否还有其他方法
有人知道吗?
您可以在列上使用 KeyAttribute
注释将其标记为主键,以便在 Insert/Update 查询时忽略它。
您也可以使用 Ignore
属性来忽略任意字段
public class BaseEntity
{
[Key]
public int PrimaryKeyColumnWillBeIgnoredOnInsert { set; get; }
[Ignore]
public int ThisColumnWillBeIgnoredAlso { set; get; }
}
检查 https://github.com/sqlkata/querybuilder/blob/master/QueryBuilder/ColumnAttribute.cs#L27