ASP.NET Core 8 Web API / C# / Dapper / Postgresql JSONB 列保存和服务,无需触及列

问题描述 投票:0回答:1

两年前,我使用 Node Express 和 Postgresql 为 Angular 前端网站编写了 ASP.NET Core 8.0 Web API,我们与前端程序员和我的 Web API 一起从该项目中养成了习惯。我在数据库中提供了一些我从未涉及过的列,前端使用该列来保存其类型的设置。我使用 Dapper 是因为我喜欢掌握 SQL 而不是 EF Core。

现在我们正在使用 Angular 的 ASP.NET Core 8 Web API 编写一个新项目,但我在 json 列方面遇到问题。

让我们举个例子吧

数据库:

create table users 
(
   user_id bigserial,
   username character varying[50],
   fullname character varying[200],
   password character varying[300],
   salt character varying[300],
   frontends_field jsonb,
   adress_data jsonb
)

public class User
{
    [Required]
    public long? User_Id { get; set; }
    
    [Required]
    [MaxLength(50)]
    public string UserName { get; set; } = string.Empty;
    
    [Required]
    [MaxLength(200)]
    public string FullName { get; set; } = string.Empty;

    [Required]
    [MaxLength(300)]
    public string Password { get; set; } = string.Empty;

    
    [MaxLength(300)]
    public string Salt { get; set; } = string.Empty;

    public ??WHICH_TYPE?? frontends_field { get; set; }
    public ??WHICH_TYPE?? adress_data { get; set; }
}

public class Adress_Data 
{
  public string? adress_name { get; set; }
  public string? streetinfo { get; set; }
  public string? buildinginfo { get; set; }
  public string? city { get; set; }
}

在控制器中,我像这样保存这些数据

[HttpPost]
public async Task<ActionResult<User>> PostUser([FromBody] User req)
{
    try
    {
        using var MyCnt = _db.GetConnection(); //Npgsqlconnection here
        {
            string MySql = """
     INSERT INTO public.users (username, fullname, password, salt, frontends_field, adress_data)
                VALUES (@username, @fullname, @password, @salt, @frontends_field, @adress_data)
                returning *;
                """;
            var result = await MyCnt.QueryFirstOrDefaultAsync<User>(MySql,req);

            return Ok(result);
        }
    }
    catch (Exception ex)
    {
        return BadRequest(ex);
    }
}

请求的 JSON 示例

{  
    "username" : "{username}",
    "fullname" : "John DOE",
    "password" : "{password}",
    "salt" "asdşfmi<sdmfpwefkpüpowefi",
    "frontends_field" : 
             { "somenumfield" : 15,
               "sometextfield" : "Cry me a river"
             },
    "adress_data" : 
             {
                 "adress_name"  : "home",
                 "streetinfo"   : "Susame Streeet No:21",
                 "buildinginfo" : "A Block",
                 "city" : "IZMIR"
             }
}

我真的被代码的 JSON 端困住了......

谢谢大家

c# json postgresql asp.net-core-webapi dapper
1个回答
0
投票

您可以尝试使用

JsonDocument
命名空间中的
JsonElement
System.Text.Json
类型来表示通用 JSON 字段,或者您也可以为结构化 JSON 字段创建自定义类。

以下是您可以参考的示例代码:

用户.cs:

using System.Text.Json;

namespace webapitest.Models
{
    public class User
    {
        public long? User_Id { get; set; }

        public string UserName { get; set; } = string.Empty;

        public string FullName { get; set; } = string.Empty;

        public string Password { get; set; } = string.Empty;

        public string Salt { get; set; } = string.Empty;

        public JsonDocument Frontends_Field { get; set; }

        public AddressData Adress_Data { get; set; }

    }
}

地址数据.cs:

namespace webapitest.Models
{
    public class AddressData
    {
        public string? Adress_Name { get; set; }
        public string? StreetInfo { get; set; }
        public string? BuildingInfo { get; set; }
        public string? City { get; set; }

    }
}

UsersController.cs

using Dapper;
using Microsoft.AspNetCore.Mvc;
using Npgsql;
using System.Text.Json;
using webapitest.Models;

namespace webapitest.Controllers
{
    [Route("api/[controller]")]
    [ApiController]

    public class UsersController : ControllerBase
    {
        private readonly NpgsqlConnection _dbConnection;

        public UsersController(NpgsqlConnection dbConnection)
        {
            _dbConnection = dbConnection;
        }

        [HttpPost]
        public async Task<ActionResult<User>> PostUser([FromBody] User req)
        {
            try
            {
                string sql = @"
                    INSERT INTO public.users (username, fullname, password, salt, frontends_field, adress_data)
                    VALUES (@UserName, @FullName, @Password, @Salt, @Frontends_Field::jsonb, @Adress_Data::jsonb)
                    RETURNING *;
                    ";

                var parameters = new
                {
                    req.UserName,
                    req.FullName,
                    req.Password,
                    req.Salt,
                    Frontends_Field = req.Frontends_Field.RootElement.ToString(),
                    Adress_Data = JsonSerializer.Serialize(req.Adress_Data)
                };

                var result = await _dbConnection.QueryFirstOrDefaultAsync(sql, parameters);
                var user = MapUser(result);

                return Ok(user);
            }
            catch (Exception ex)
            {
                return BadRequest(ex);
            }
        }

        private static User MapUser(dynamic record)
        {
            return new User
            {
                User_Id = record.user_id,
                UserName = record.username,
                FullName = record.fullname,
                Password = record.password,
                Salt = record.salt,
                Frontends_Field = JsonDocument.Parse((string)record.frontends_field),
                Adress_Data = JsonSerializer.Deserialize<AddressData>((string)record.adress_data)
            };
        }

    }
}

样品要求:

{
        "username" : "",
        "fullname" : "John DOE",
        "password" : "",
        "salt": "asdşfmi<sdmfpwefkpüpowefi",
        "frontends_field" : 
        {
            "somenumfield" : 15,
            "sometextfield" : "Cry me a river"
        },
        "adress_data" : 
        {
            "adress_name"  : "home",
            "streetinfo"   : "Susame Street No:21",
            "buildinginfo" : "A Block",
            "city" : "IZMIR"
        }
    }

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.