我在PostgreSQL中有下表:
CREATE TABLE "user" (
id UUID NOT NULL,
name VARCHAR (50) NULL,
email VARCHAR (50) NOT NULL,
CONSTRAINT pk_user PRIMARY KEY (id)
);
此数据库中的所有函数在参数名称上均使用下划线(_
)前缀。示例:
CREATE OR REPLACE FUNCTION user_read_by_id
(
_id uuid
)
RETURNS SETOF "user"
LANGUAGE 'plpgsql'
AS
$BODY$
BEGIN
RETURN QUERY
SELECT
*
FROM
"user"
WHERE
"id" = _id;
END
$BODY$;
和
CREATE OR REPLACE FUNCTION user_create
(
_id uuid,
_name varchar(50),
_email varchar(50)
)
RETURNS VOID
LANGUAGE 'plpgsql'
AS
$$
BEGIN
INSERT INTO "user"
(
id,
name,
email
)
VALUES
(
_id,
_name,
_email
);
END
$$
在使用Dapper的C#代码中,我需要能够使用此下划线前缀映射User
对象参数,但也要使其也映射回没有下划线前缀的结果集。
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
DefaultTypeMap.MatchNamesWithUnderscores = true;
// This works because I am manually setting the `_id` parameter.
// Ideally, it would match the User object and just use `Id`.
using(var connection = new NpgsqlConnection(ConnectionString))
{
var results = await connection.QueryAsync<User>(
"user_read_by_id",
new { _id = new Guid("38745b2e-436c-4593-827e-6ae123f12db5") },
commandType: CommandType.StoredProcedure);
var user = results.SingleOrDefault();
}
// This breaks because the User object doesn't map correctly
// to the parameters of the PgSQL function.
using(var connection = new NpgsqlConnection(ConnectionString))
{
var results = await connection.ExecuteAsync(
"user_create",
new User
{
Id = new Guid("38745b2e-436c-4593-827e-6ae123f12db5"),
Name = "John",
Email = "j.smith@example.com"
},
commandType: CommandType.StoredProcedure);
}
是否可以通过某种方式创建仅自动在param对象上加下划线前缀的映射器?
答案 0 :(得分:0)
也许有更好的方法可以解决此问题,但是我创建了一种通过反射param对象来处理此问题的方法,并创建了一个新的DynamicParameters
参数。
using(var connection = new NpgsqlConnection(ConnectionString))
{
var results = await connection.ExecuteAsync(
"user_create",
ToParam(new User
{
Id = new Guid("38745b2e-436c-4593-827e-6ae123f12db5"),
Name = "John",
Email = "j.smith@example.com"
}),
commandType: CommandType.StoredProcedure);
}
private DynamicParameters ToParam<T>(T obj)
{
var dp = new DynamicParameters();
var properties = typeof(T).GetProperties();
foreach(var property in properties)
{
dp.Add($"_{SnakeCase(property.Name)}", property.GetValue(obj));
}
return dp;
}
private string SnakeCase(string input)
{
if(string.IsNullOrWhiteSpace(input))
{
return input;
}
var startUnderscores = Regex.Match(input, @"^_+");
return startUnderscores + Regex.Replace(input, @"([a-z0-9])([A-Z])", "$1_$2").ToLowerInvariant();
}