code-server多用户隔离方案:从容器化部署到企业级实践指南
在当今远程协作日益普遍的开发环境中,code-server作为一款能在浏览器中运行VS Code的开源工具,极大地提升了开发灵活性。然而,其默认的单用户架构在企业团队使用时面临着权限管理、环境隔离和资源分配等关键挑战。本文将深入剖析这些痛点,提出基于容器化技术的创新隔离方案,并提供从部署实施到高级优化的完整指南,帮助团队构建安全、高效的多人协作开发平台。
⚠️ 问题剖析:单用户架构的协作困境
code-server的单用户设计在团队场景下暴露出诸多限制,这些问题随着团队规模扩大而愈发明显:
权限边界模糊的安全隐患
在默认配置下,所有用户共享同一套系统权限,这意味着:
- 开发人员可以访问其他团队成员的代码和配置
- 缺乏细粒度的文件访问控制,敏感数据面临泄露风险
- 恶意或误操作可能影响整个系统稳定性
真实案例:某创业公司因未隔离code-server环境,导致实习生误删核心项目配置文件,造成4小时业务中断。
开发环境的"相互污染"
当多个开发者共用一个code-server实例时,环境冲突成为常态:
- 扩展安装和更新相互干扰,出现"一人安装、全队遭殃"的情况
- 工作区配置频繁被覆盖,个性化开发环境难以维持
- 依赖包版本冲突,导致"在我电脑上能运行"的经典问题
图1:code-server默认单用户界面,缺乏用户隔离机制
资源竞争与性能瓶颈
单实例运行模式无法有效分配计算资源:
- CPU和内存被少数活跃用户占用,导致整体响应缓慢
- 缺乏资源使用限制,单个用户的密集型操作影响所有人
- 无法针对不同项目需求调整资源配额
🛠️ 方案设计:容器化隔离架构详解
针对上述问题,我们提出基于容器化技术的多用户隔离方案,通过Docker容器为每个用户提供独立的code-server运行环境。
容器化vs.Unix用户隔离:技术选型对比
| 特性 | 容器化隔离 | Unix用户隔离 |
|---|---|---|
| 隔离级别 | 进程级完全隔离 | 用户级权限隔离 |
| 环境一致性 | 极高,容器镜像保证环境一致 | 依赖系统配置,易产生差异 |
| 资源控制 | 精细的CPU/内存限制 | 较粗粒度的资源分配 |
| 移植性 | 跨平台支持,环境一致性好 | 依赖特定Unix系统 |
| 管理复杂度 | 需容器编排知识 | 系统用户管理经验即可 |
| 启动速度 | 秒级启动 | 毫秒级启动 |
flowchart TD
Client[用户浏览器] --> LoadBalancer[负载均衡器]
LoadBalancer --> AuthService[认证服务]
AuthService --> |验证身份| ContainerOrchestrator[容器编排平台]
ContainerOrchestrator --> |动态调度| DockerHost1[Docker主机1]
ContainerOrchestrator --> |动态调度| DockerHost2[Docker主机2]
DockerHost1 --> Container1[code-server容器 - 用户A]
DockerHost1 --> Container2[code-server容器 - 用户B]
DockerHost2 --> Container3[code-server容器 - 用户C]
Container1 --> VolumeA[/用户A数据卷/]
Container2 --> VolumeB[/用户B数据卷/]
Container3 --> VolumeC[/用户C数据卷/]
图2:容器化多用户隔离架构流程图
核心技术组件解析
「容器编排」 - 通俗解释:自动化管理多个容器的创建、运行和销毁的系统
采用Docker Compose或Kubernetes实现容器生命周期管理,根据用户需求动态调整资源分配。
「数据卷挂载」 - 通俗解释:将容器内的数据持久化存储到宿主机的技术
通过命名卷( Named Volume )为每个用户提供独立的文件存储空间,确保数据隔离与持久化。
「反向代理与路由」 - 通俗解释:统一入口并将请求转发到对应容器的中间层
使用Nginx或Traefik实现基于子域名或路径的请求路由,将用户请求定向到其专属容器。
🚀 实施指南:从零构建容器化多用户环境
1. 环境准备与基础组件安装
# 更新系统并安装Docker
sudo apt update && sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update && sudo apt install -y docker-ce docker-compose
# 安装Nginx作为反向代理
sudo apt install -y nginx
# 安装Git并克隆code-server仓库
git clone https://gitcode.com/GitHub_Trending/co/code-server
cd code-server
图3:code-server安装脚本执行界面,显示安装过程和参数选项
2. 容器化部署脚本实现
创建code-server-manager.sh管理脚本,用于自动化创建和管理用户容器:
#!/bin/bash
# code-server多用户容器管理脚本
# 支持创建、删除、列出用户容器实例
set -euo pipefail
# 配置参数
BASE_DIR="/opt/code-server" # 基础工作目录
DATA_VOLUME_BASE="${BASE_DIR}/data" # 用户数据存储目录
TEMPLATE_DIR="${BASE_DIR}/templates" # 环境模板目录
NGINX_CONFIG="/etc/nginx/conf.d/code-server.conf" # Nginx配置文件
PORT_RANGE_START=8080 # 起始端口范围
MAX_USER_CONTAINERS=50 # 最大用户容器数
# 确保基础目录存在
mkdir -p "${BASE_DIR}" "${DATA_VOLUME_BASE}" "${TEMPLATE_DIR}"
# 命令帮助信息
usage() {
echo "Usage: $0 {create|delete|list|start|stop} [username]"
echo " create <username> - 创建新用户容器"
echo " delete <username> - 删除用户容器"
echo " list - 列出所有用户容器"
echo " start <username> - 启动用户容器"
echo " stop <username> - 停止用户容器"
exit 1
}
# 创建用户容器
create_user() {
local username=$1
# 检查用户是否已存在
if [ "$(docker ps -a --filter "name=code-server-${username}" --format '{{.Names}}')" = "code-server-${username}" ]; then
echo "Error: User container for ${username} already exists"
exit 1
fi
# 检查是否超过最大用户数
local current_containers=$(docker ps -a --filter "name=code-server-" --format '{{.Names}}' | wc -l)
if [ $current_containers -ge $MAX_USER_CONTAINERS ]; then
echo "Error: Maximum number of user containers (${MAX_USER_CONTAINERS}) reached"
exit 1
fi
# 分配端口
local port=$((PORT_RANGE_START + current_containers))
# 创建数据卷目录
local data_volume="${DATA_VOLUME_BASE}/${username}"
mkdir -p "${data_volume}"
chmod 700 "${data_volume}"
# 生成随机密码
local password=$(openssl rand -hex 12)
# 创建并启动容器
docker run -d \
--name "code-server-${username}" \
--restart unless-stopped \
--memory 2g \
--memory-swap 2g \
--cpus 1 \
-p 127.0.0.1:${port}:8080 \
-v "${data_volume}:/home/coder" \
-e PASSWORD="${password}" \
codercom/code-server:latest \
--auth password \
--bind-addr 0.0.0.0:8080 \
--user-data-dir /home/coder/.local/share/code-server \
--extensions-dir /home/coder/.local/share/code-server/extensions
# 更新Nginx配置
update_nginx_config
echo "Successfully created code-server container for ${username}"
echo "Access URL: https://code.example.com/${username}"
echo "Password: ${password}"
echo "Container name: code-server-${username}"
echo "Allocated port: ${port}"
}
# 其他函数(delete_user, list_users, start_user, stop_user, update_nginx_config)省略...
# 命令解析
case "$1" in
create)
[ $# -ne 2 ] && usage
create_user "$2"
;;
delete)
[ $# -ne 2 ] && usage
delete_user "$2"
;;
list)
list_users
;;
start)
[ $# -ne 2 ] && usage
start_user "$2"
;;
stop)
[ $# -ne 2 ] && usage
stop_user "$2"
;;
*)
usage
;;
esac
3. Nginx反向代理配置
创建/etc/nginx/conf.d/code-server.conf配置文件:
server {
listen 80;
server_name code.example.com;
# 重定向到HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name code.example.com;
# SSL配置
ssl_certificate /etc/letsencrypt/live/code.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/code.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# 配置WebSocket支持
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 用户容器路由
location ~ ^/([a-zA-Z0-9_-]+)(/.*)?$ {
# 排除管理路径
if ($1 ~* "admin") {
proxy_pass http://127.0.0.1:8000$2$is_args$args;
break;
}
# 动态获取用户容器端口
set $user $1;
set $port "";
# 通过查找容器标签获取端口
set_by_lua_block $port {
local handle = io.popen("docker inspect -f '{{range $p, $conf := .NetworkSettings.Ports}}{{if eq $p \"8080/tcp\"}}{{(index $conf 0).HostPort}}{{end}}{{end}}' code-server-" .. ngx.var.user)
local port = handle:read("*a")
handle:close()
return port:gsub("%s+", "")
}
# 如果端口未找到,返回404
if ($port = "") {
return 404 "User not found or container not running";
}
# 代理到用户容器
proxy_pass http://127.0.0.1:$port$2$is_args$args;
}
}
4. 自动化部署脚本生成器
为简化部署流程,我们设计了一个交互式配置生成器,可根据实际需求生成定制化部署脚本:
#!/bin/bash
# code-server多用户环境部署脚本生成器
echo "===== code-server多用户环境部署脚本生成器 ====="
echo "请回答以下问题,我们将为您生成定制化部署脚本"
# 获取用户输入
read -p "请输入域名 (例如: code.example.com): " DOMAIN
read -p "请输入最大用户数: " MAX_USERS
read -p "请输入每个用户默认内存限制 (例如: 2g): " MEM_LIMIT
read -p "请输入每个用户默认CPU限制 (例如: 1): " CPU_LIMIT
read -p "请输入数据存储路径 (默认: /opt/code-server/data): " DATA_PATH
read -p "请输入起始端口号 (默认: 8080): " PORT_START
# 使用默认值
DATA_PATH=${DATA_PATH:-"/opt/code-server/data"}
PORT_START=${PORT_START:-8080}
# 生成部署脚本
cat > deploy-code-server.sh << EOF
#!/bin/bash
# 自动生成的code-server多用户环境部署脚本
# 生成时间: $(date)
# 域名: $DOMAIN
# 最大用户数: $MAX_USERS
# 每个用户内存限制: $MEM_LIMIT
# 每个用户CPU限制: $CPU_LIMIT
# 数据存储路径: $DATA_PATH
# 起始端口: $PORT_START
set -euo pipefail
# 安装依赖
echo "正在安装依赖..."
sudo apt update && sudo apt install -y docker-ce docker-compose nginx certbot python3-certbot-nginx
# 创建目录结构
echo "创建目录结构..."
sudo mkdir -p $DATA_PATH /opt/code-server/templates
# 下载code-server镜像
echo "拉取code-server镜像..."
sudo docker pull codercom/code-server:latest
# 生成管理脚本
echo "生成管理脚本..."
sudo tee /usr/local/bin/code-server-manager << 'EOF_MANAGER'
$(cat code-server-manager.sh)
EOF_MANAGER
# 设置权限
sudo chmod +x /usr/local/bin/code-server-manager
# 配置Nginx
echo "配置Nginx..."
sudo tee /etc/nginx/conf.d/code-server.conf << EOF_NGINX
server {
listen 80;
server_name $DOMAIN;
location / {
return 301 https://\$host\$request_uri;
}
}
server {
listen 443 ssl;
server_name $DOMAIN;
ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
location ~ ^/([a-zA-Z0-9_-]+)(/.*)?\$ {
if (\$1 ~* "admin") {
proxy_pass http://127.0.0.1:8000\$2\$is_args\$args;
break;
}
set \$user \$1;
set \$port "";
set_by_lua_block \$port {
local handle = io.popen("docker inspect -f '{{range \$p, \$conf := .NetworkSettings.Ports}}{{if eq \$p \"8080/tcp\"}}{{(index \$conf 0).HostPort}}{{end}}{{end}}' code-server-" .. ngx.var.user)
local port = handle:read("*a")
handle:close()
return port:gsub("%s+", "")
}
if (\$port = "") {
return 404 "User not found or container not running";
}
proxy_pass http://127.0.0.1:\$port\$2\$is_args\$args;
}
}
EOF_NGINX
# 获取SSL证书
echo "获取SSL证书..."
sudo certbot --nginx -d $DOMAIN --agree-tos --non-interactive -m admin@$DOMAIN
# 重启Nginx
sudo systemctl restart nginx
echo "部署完成! 使用以下命令管理用户:"
echo " code-server-manager create <username> - 创建用户"
echo " code-server-manager list - 列出用户"
echo " code-server-manager delete <username> - 删除用户"
EOF
# 设置执行权限
chmod +x deploy-code-server.sh
echo "部署脚本已生成: ./deploy-code-server.sh"
echo "请运行该脚本完成部署"
🔍 场景拓展:高级功能与企业级优化
动态资源调度实现
「动态资源调度」 - 通俗解释:根据实际使用情况自动调整容器资源分配的技术
通过Docker的资源限制与监控工具结合,实现基于使用情况的动态资源调整:
#!/bin/bash
# 动态资源调度脚本,根据CPU使用率调整容器资源
# 监控周期(秒)
INTERVAL=60
# CPU使用率阈值(%)
HIGH_THRESHOLD=80
# 低CPU使用率阈值(%)
LOW_THRESHOLD=30
# 资源调整步长
STEP=0.5
while true; do
# 获取所有code-server容器
containers=$(docker ps --filter "name=code-server-" --format "{{.Names}}")
for container in $containers; do
# 获取容器当前CPU使用率
cpu_usage=$(docker stats --no-stream --format "{{.CPUPerc}}" $container | sed 's/%//')
# 获取当前CPU限制
current_cpu=$(docker inspect -f '{{.HostConfig.NanoCpus}}' $container)
current_cpu_cores=$(echo "scale=2; $current_cpu / 1000000000" | bc)
# 如果CPU使用率超过阈值,增加资源
if (( $(echo "$cpu_usage > $HIGH_THRESHOLD" | bc -l) )); then
new_cpu_cores=$(echo "scale=2; $current_cpu_cores + $STEP" | bc)
# 限制最大CPU为4核
if (( $(echo "$new_cpu_cores <= 4" | bc -l) )); then
echo "Increasing CPU for $container from $current_cpu_cores to $new_cpu_cores"
docker update --cpus $new_cpu_cores $container
fi
# 如果CPU使用率过低,减少资源
elif (( $(echo "$cpu_usage < $LOW_THRESHOLD" | bc -l) )); then
new_cpu_cores=$(echo "scale=2; $current_cpu_cores - $STEP" | bc)
# 保证最小CPU为0.5核
if (( $(echo "$new_cpu_cores >= 0.5" | bc -l) )); then
echo "Decreasing CPU for $container from $current_cpu_cores to $new_cpu_cores"
docker update --cpus $new_cpu_cores $container
fi
fi
done
sleep $INTERVAL
done
跨节点负载均衡配置
对于大规模部署,可采用多节点架构实现高可用和负载均衡:
# docker-compose.yml - 多节点负载均衡配置
version: '3.8'
services:
traefik:
image: traefik:v2.5
command:
- "--providers.docker=true"
- "--providers.docker.swarmmode=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=admin@example.com"
- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- letsencrypt:/letsencrypt
deploy:
placement:
constraints: [node.role == manager]
code-server-template:
image: codercom/code-server:latest
deploy:
replicas: 0 # 初始不运行任何实例
resources:
limits:
cpus: '2'
memory: 4G
reservations:
cpus: '0.5'
memory: 1G
restart_policy:
condition: on-failure
environment:
- PASSWORD=changeme
volumes:
- userdata:/home/coder
command: --auth password --bind-addr 0.0.0.0:8080
volumes:
letsencrypt:
userdata:
环境模板管理系统
利用code-server的模板功能,为不同项目团队提供预配置开发环境:
图4:code-server环境模板选择界面,可以为不同开发场景提供预配置环境
创建模板管理脚本:
#!/bin/bash
# code-server环境模板管理工具
TEMPLATE_DIR="/opt/code-server/templates"
# 创建模板
create_template() {
local template_name=$1
local source_container=$2
# 确保模板目录存在
mkdir -p "${TEMPLATE_DIR}/${template_name}"
echo "从容器${source_container}创建模板${template_name}..."
# 导出容器文件系统
docker export ${source_container} | tar -x -C "${TEMPLATE_DIR}/${template_name}"
# 创建元数据文件
cat > "${TEMPLATE_DIR}/${template_name}/template.json" << EOF
{
"name": "${template_name}",
"description": "Template created from ${source_container}",
"created": "$(date -Iseconds)",
"size": "$(du -sh "${TEMPLATE_DIR}/${template_name}" | cut -f1)"
}
EOF
echo "模板${template_name}创建成功"
}
# 从模板创建用户环境
create_from_template() {
local username=$1
local template_name=$2
if [ ! -d "${TEMPLATE_DIR}/${template_name}" ]; then
echo "Error: Template ${template_name} not found"
exit 1
fi
echo "从模板${template_name}为用户${username}创建环境..."
# 创建用户数据目录
local data_volume="${DATA_VOLUME_BASE}/${username}"
mkdir -p "${data_volume}"
# 复制模板内容
cp -r "${TEMPLATE_DIR}/${template_name}/." "${data_volume}/"
# 创建用户容器
/usr/local/bin/code-server-manager create "${username}"
echo "用户${username}环境已从模板${template_name}创建"
}
# 列出所有模板
list_templates() {
echo "可用环境模板:"
for template in $(ls -d "${TEMPLATE_DIR}"/*/ 2>/dev/null | xargs -n1 basename); do
local desc=$(jq -r '.description' "${TEMPLATE_DIR}/${template}/template.json")
local size=$(jq -r '.size' "${TEMPLATE_DIR}/${template}/template.json")
echo " ${template}: ${desc} (Size: ${size})"
done
}
# 命令解析
case "$1" in
create-template)
[ $# -ne 3 ] && echo "Usage: $0 create-template <template-name> <source-container>" && exit 1
create_template "$2" "$3"
;;
from-template)
[ $# -ne 3 ] && echo "Usage: $0 from-template <username> <template-name>" && exit 1
create_from_template "$2" "$3"
;;
list-templates)
list_templates
;;
*)
echo "Usage:"
echo " $0 create-template <template-name> <source-container> - 从容器创建模板"
echo " $0 from-template <username> <template-name> - 从模板创建用户环境"
echo " $0 list-templates - 列出所有模板"
exit 1
;;
esac
🔒 安全加固与性能调优
生产环境安全配置清单
-
容器安全加固
# 启用Docker内容信任 export DOCKER_CONTENT_TRUST=1 # 设置容器只读文件系统 docker run --read-only ... # 禁止特权模式 # 在docker-compose.yml中设置 # privileged: false -
网络安全配置
# 设置防火墙规则 ufw allow 443/tcp ufw allow 80/tcp ufw default deny incoming # 启用容器网络隔离 docker network create --internal code-server-internal -
数据备份策略
# 创建自动备份脚本 cat > /etc/cron.daily/backup-code-server << 'EOF' #!/bin/bash BACKUP_DIR="/var/backups/code-server" TIMESTAMP=$(date +%Y%m%d-%H%M%S) mkdir -p $BACKUP_DIR # 备份所有用户数据 for user in $(ls /opt/code-server/data); do tar -czf $BACKUP_DIR/${user}-${TIMESTAMP}.tar.gz /opt/code-server/data/${user} done # 删除7天前的备份 find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete EOF chmod +x /etc/cron.daily/backup-code-server
性能监控面板配置
使用Prometheus和Grafana监控系统性能:
# docker-compose.monitor.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- "9090:9090"
grafana:
image: grafana/grafana
volumes:
- grafana-data:/var/lib/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=secret
depends_on:
- prometheus
volumes:
prometheus-data:
grafana-data:
📝 总结与展望
本文详细介绍了基于容器化技术的code-server多用户隔离方案,通过Docker容器实现了用户环境的完全隔离,解决了单用户架构下的权限控制、环境冲突和资源竞争问题。相比传统的Unix用户隔离方案,容器化方案提供了更高的隔离级别、更好的环境一致性和更精细的资源控制。
实施该方案后,团队可以获得:
- 安全可控的多用户开发环境
- 一致的开发体验和环境配置
- 灵活的资源分配和扩展能力
- 便捷的环境管理和模板系统
未来可以进一步探索的方向:
- 与企业SSO系统集成,实现统一身份认证
- 开发Web管理界面,简化用户和资源管理
- 结合Kubernetes实现更强大的容器编排和自动扩缩容
- 引入AI辅助的资源调度优化,提高资源利用率
通过本文提供的方案和工具,企业可以快速构建安全、高效的多人协作开发平台,充分发挥code-server的优势,同时解决团队协作中的实际问题。
📚 附录:常用命令速查表
| 命令 | 功能描述 |
|---|---|
code-server-manager create <username> |
创建新用户容器 |
code-server-manager list |
列出所有用户容器 |
code-server-manager delete <username> |
删除用户容器 |
docker stats |
查看容器资源使用情况 |
./dynamic-resource-scheduler.sh |
启动动态资源调度 |
code-server-template create-template <name> <container> |
创建环境模板 |
code-server-template from-template <user> <template> |
从模板创建用户 |
journalctl -u nginx -f |
查看Nginx实时日志 |
docker logs -f code-server-<username> |
查看用户容器日志 |
GLM-5智谱 AI 正式发布 GLM-5,旨在应对复杂系统工程和长时域智能体任务。Jinja00
GLM-5.1GLM-5.1是智谱迄今最智能的旗舰模型,也是目前全球最强的开源模型。GLM-5.1大大提高了代码能力,在完成长程任务方面提升尤为显著。和此前分钟级交互的模型不同,它能够在一次任务中独立、持续工作超过8小时,期间自主规划、执行、自我进化,最终交付完整的工程级成果。Jinja00
LongCat-AudioDiT-1BLongCat-AudioDiT 是一款基于扩散模型的文本转语音(TTS)模型,代表了当前该领域的最高水平(SOTA),它直接在波形潜空间中进行操作。00- QQwen3.5-397B-A17BQwen3.5 实现了重大飞跃,整合了多模态学习、架构效率、强化学习规模以及全球可访问性等方面的突破性进展,旨在为开发者和企业赋予前所未有的能力与效率。Jinja00
HY-Embodied-0.5这是一套专为现实世界具身智能打造的基础模型。该系列模型采用创新的混合Transformer(Mixture-of-Transformers, MoT) 架构,通过潜在令牌实现模态特异性计算,显著提升了细粒度感知能力。Jinja00
FreeSql功能强大的对象关系映射(O/RM)组件,支持 .NET Core 2.1+、.NET Framework 4.0+、Xamarin 以及 AOT。C#00