惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
量子位
小众软件
小众软件
C
Cybersecurity and Infrastructure Security Agency CISA
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tenable Blog
V
Vulnerabilities – Threatpost
Know Your Adversary
Know Your Adversary
T
Threat Research - Cisco Blogs
Latest news
Latest news
Spread Privacy
Spread Privacy
C
Cyber Attacks, Cyber Crime and Cyber Security
NISL@THU
NISL@THU
T
Tor Project blog
Hacker News: Ask HN
Hacker News: Ask HN
V2EX - 技术
V2EX - 技术
T
The Exploit Database - CXSecurity.com
博客园 - 三生石上(FineUI控件)
K
Kaspersky official blog
Cyberwarzone
Cyberwarzone
博客园 - 叶小钗
博客园 - 聂微东
Last Week in AI
Last Week in AI
爱范儿
爱范儿
腾讯CDC
博客园 - Franky
美团技术团队
J
Java Code Geeks
O
OpenAI News
L
Lohrmann on Cybersecurity
Simon Willison's Weblog
Simon Willison's Weblog
有赞技术团队
有赞技术团队
T
Threatpost
G
GRAHAM CLULEY
Hugging Face - Blog
Hugging Face - Blog
博客园 - 【当耐特】
宝玉的分享
宝玉的分享
I
Intezer
N
News and Events Feed by Topic
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Blog of Author Tim Ferriss
S
Security @ Cisco Blogs
Forbes - Security
Forbes - Security
N
News | PayPal Newsroom
Stack Overflow Blog
Stack Overflow Blog
Scott Helme
Scott Helme
H
Hacker News: Front Page
Cloudbric
Cloudbric

博客园 - 我才是银古

第16章:常见问题、排错与最佳实践 第15章:扩展生态、MCAD 与外部集成 第12章:实战案例:机械结构与 3D 打印零件 第14章:构建、测试、调试与贡献流程 第13章:OpenSCAD 源码架构与核心执行流程 第11章:预览、渲染、网格精度与性能优化 第09章:列表推导、递归与算法建模 第08章:参数化零件库与复用设计 第10章:导入导出、命令行与自动化 第06章:CSG 布尔建模方法 第07章:二维图形、拉伸、旋转与投影 第05章:基础几何、坐标系与变换 第04章:参数、变量、函数、模块与作用域 OpenSCAD 教程目录 第03章:OpenSCAD 语言基础 第02章:安装、环境配置与开发工作流 第01章:OpenSCAD 项目全景与学习路线 第02章:源码获取、编译与开发环境配置 第01章:OCCT项目全景与学习路线 第18章:二次开发实战与综合案例 第18章:综合实战案例 第17章:数据交换与协同 第16章:源码架构与二次开发 第15章:插件与自定义工作台开发 第14章:Python脚本宏与自动化 第13章:FEM仿真分析 第12章:CAM数控加工 第11章:SurfaceMesh与逆向工程 第10章:Draft二维绘图与BIM建筑 第09章:工程图TechDraw 第07章:参数化表达式与Spreadsheet 第08章:装配设计Assembly 第06章:Part工作台与几何内核 第05章:PartDesign实体特征建模 第04章:草图Sketcher约束建模 第02章:安装版本与工作环境配置 第03章:界面工作台与基础操作 第01章:项目全景与学习路线 第十二章:插件开发、研究功能与最佳实践 第十章:定时任务与自动化(Cron) 第七章:技能、记忆与自学习闭环 第八章:MCP 集成与上下文文件 第六章:工具系统与终端后端 第五章:模型供应商与配置体系 Hermes Agent 教程目录 第十一章:语音、视觉、浏览器与子代理协作 第四章:CLI/TUI 与会话管理 第十二章:学习路线、实战方案与最佳实践 第十一章:源码结构、开发调试与插件开发 第十章:自动化、远程访问、日志与排障 第九章:Control UI、节点、Canvas 与语音能力 第七章:工具、技能、插件与能力扩展 第八章:安全模型、访问控制与沙箱实践 第六章:Agent 工作区、会话与多智能体路由 第五章:多通道消息接入与聊天平台配置 第四章:配置体系、模型接入与认证管理 第三章:Gateway 架构、协议与运行机制 第二章:安装、环境准备与快速上手 第一章:OpenClaw 项目概览与核心定位 oh-my-openagent 教程目录 09-命令模型回退与配置参考 10-实战案例最佳实践与故障排除 05-工作模式-Ultrawork-Prometheus-Atlas 08-Hooks与MCP系统 06-Category与Skill系统 07-核心工具链 04-智能体全景详解 03-安装与环境配置 02-整体架构与多模型编排机制 01-项目简介与核心理念 01-项目概览与学习路线 02-安装部署与工具适配 03-Skill机制与using-superpowers 05-TDD系统化调试与完成前验证 04-需求澄清方案设计与计划编写 07-并行智能体子智能体与Git-Worktree 第六章:代码审查、反馈处理与分支收尾 08-中国特色Skills与本土团队落地 09-MCP构建工作流执行与自定义Skill 第23章:FreeCAD-Python-API Clipper2 C# 源码解读教程 第19章:PolyTree 多边形树结构 第20章:实际应用与最佳实践 第18章:Minkowski 和与差 第17章:RectClip 矩形裁剪优化 第16章:ClipperOffset 偏移类详解 第15章:填充规则详解 第14章:布尔运算执行流程 第13章:ClipperD 浮点裁剪类 第11章:OutRec 与 OutPt 输出结构 第9章:Active 活动边结构 第10章:Vertex 顶点与 LocalMinima 局部极小值 第12章:Clipper64 裁剪类详解 第7章:高精度运算与128位整数 第8章:ClipperBase 基类详解 第5章:枚举类型与常量定义 第6章:InternalClipper 内部工具类 第2章:核心数据结构 - Point64、PointD 第3章:路径与多边形表示 - Path64、PathD、Paths64、PathsD 第4章:矩形边界 - Rect64、RectD
数据库与项目管理
我才是银古 · 2026-06-20 · via 博客园 - 我才是银古

第十七章:数据库与项目管理

17.1 数据库模块概述

17.1.1 数据库相关模块

LightCAD包含两个数据库相关的模块:

模块 说明
LightCAD.DBHelper 数据库帮助工具,提供通用的数据库操作接口
LightCAD.DBUtility 数据库工具类,封装具体的数据库访问逻辑

17.1.2 项目管理模块

模块 说明
LightCAD.PrjManager 项目管理器,管理项目生命周期
LightCAD.LocalSolution 本地工作空间管理

17.2 数据库帮助工具(DBHelper)

17.2.1 数据库连接管理

public class DBHelper
{
    private string connectionString;

    public DBHelper(string connectionString)
    {
        this.connectionString = connectionString;
    }

    /// <summary>
    /// 执行查询,返回数据表
    /// </summary>
    public DataTable ExecuteQuery(string sql, params DbParameter[] parameters)
    {
        using var connection = CreateConnection();
        connection.Open();

        using var command = connection.CreateCommand();
        command.CommandText = sql;
        if (parameters != null)
        {
            command.Parameters.AddRange(parameters);
        }

        using var adapter = CreateDataAdapter(command);
        var table = new DataTable();
        adapter.Fill(table);
        return table;
    }

    /// <summary>
    /// 执行非查询命令(INSERT、UPDATE、DELETE)
    /// </summary>
    public int ExecuteNonQuery(string sql, params DbParameter[] parameters)
    {
        using var connection = CreateConnection();
        connection.Open();

        using var command = connection.CreateCommand();
        command.CommandText = sql;
        if (parameters != null)
        {
            command.Parameters.AddRange(parameters);
        }

        return command.ExecuteNonQuery();
    }

    /// <summary>
    /// 执行标量查询
    /// </summary>
    public object ExecuteScalar(string sql, params DbParameter[] parameters)
    {
        using var connection = CreateConnection();
        connection.Open();

        using var command = connection.CreateCommand();
        command.CommandText = sql;
        if (parameters != null)
        {
            command.Parameters.AddRange(parameters);
        }

        return command.ExecuteScalar();
    }

    /// <summary>
    /// 事务执行
    /// </summary>
    public void ExecuteInTransaction(Action<DbConnection, DbTransaction> action)
    {
        using var connection = CreateConnection();
        connection.Open();

        using var transaction = connection.BeginTransaction();
        try
        {
            action(connection, transaction);
            transaction.Commit();
        }
        catch
        {
            transaction.Rollback();
            throw;
        }
    }
}

17.2.2 数据库工具类

public class DBUtility
{
    /// <summary>
    /// 保存实体到数据库
    /// </summary>
    public void SaveEntity(LcEntity entity, DBHelper db)
    {
        var sql = @"INSERT INTO Entities
            (Handle, Guid, TypeName, LayerName, ColorR, ColorG, ColorB,
             LineType, LineWeight, IsVisible, GeometryData)
            VALUES
            (@Handle, @Guid, @TypeName, @LayerName, @ColorR, @ColorG, @ColorB,
             @LineType, @LineWeight, @IsVisible, @GeometryData)
            ON CONFLICT(Handle) DO UPDATE SET
            GeometryData = @GeometryData";

        db.ExecuteNonQuery(sql,
            new DbParameter("@Handle", entity.Handle),
            new DbParameter("@Guid", entity.Guid.ToString()),
            new DbParameter("@TypeName", entity.TypeName),
            new DbParameter("@LayerName", entity.LayerName),
            new DbParameter("@ColorR", entity.Color.R),
            new DbParameter("@ColorG", entity.Color.G),
            new DbParameter("@ColorB", entity.Color.B),
            new DbParameter("@LineType", entity.LineType ?? ""),
            new DbParameter("@LineWeight", entity.LineWeight),
            new DbParameter("@IsVisible", entity.IsVisible),
            new DbParameter("@GeometryData", SerializeGeometry(entity))
        );
    }

    /// <summary>
    /// 从数据库加载实体
    /// </summary>
    public List<LcEntity> LoadEntities(DBHelper db)
    {
        var sql = "SELECT * FROM Entities WHERE IsVisible = 1";
        var table = db.ExecuteQuery(sql);
        var entities = new List<LcEntity>();

        foreach (DataRow row in table.Rows)
        {
            var entity = DeserializeEntity(row);
            if (entity != null)
            {
                entities.Add(entity);
            }
        }

        return entities;
    }
}

17.3 项目管理器(PrjManager)

17.3.1 项目结构

public class Project
{
    /// <summary>
    /// 项目唯一标识
    /// </summary>
    public LcGuid Guid { get; set; }

    /// <summary>
    /// 项目名称
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 项目描述
    /// </summary>
    public string Description { get; set; }

    /// <summary>
    /// 项目路径
    /// </summary>
    public string ProjectPath { get; set; }

    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime CreatedAt { get; set; }

    /// <summary>
    /// 最后修改时间
    /// </summary>
    public DateTime ModifiedAt { get; set; }

    /// <summary>
    /// 项目文件列表
    /// </summary>
    public List<ProjectFile> Files { get; set; } = new();

    /// <summary>
    /// 项目设置
    /// </summary>
    public ProjectSettings Settings { get; set; } = new();
}

public class ProjectFile
{
    public string FileName { get; set; }
    public string RelativePath { get; set; }
    public string FileType { get; set; }
    public DateTime ModifiedAt { get; set; }
    public long FileSize { get; set; }
}

public class ProjectSettings
{
    public LengthUnit DefaultUnit { get; set; } = LengthUnit.Millimeter;
    public double DefaultScale { get; set; } = 1.0;
    public string DefaultFont { get; set; } = "SimSun";
    public string DefaultLayer { get; set; } = "0";
}

17.3.2 项目管理器

public class PrjManager
{
    private Project currentProject;
    private string projectRoot;

    /// <summary>
    /// 当前项目
    /// </summary>
    public Project CurrentProject => currentProject;

    /// <summary>
    /// 创建新项目
    /// </summary>
    public Project CreateProject(string name, string path)
    {
        var project = new Project
        {
            Guid = LcGuid.NewGuid(),
            Name = name,
            ProjectPath = path,
            CreatedAt = DateTime.Now,
            ModifiedAt = DateTime.Now
        };

        // 创建项目目录结构
        Directory.CreateDirectory(path);
        Directory.CreateDirectory(Path.Combine(path, "Drawings"));
        Directory.CreateDirectory(Path.Combine(path, "Models"));
        Directory.CreateDirectory(Path.Combine(path, "Templates"));
        Directory.CreateDirectory(Path.Combine(path, "Output"));

        // 保存项目文件
        SaveProjectFile(project);

        currentProject = project;
        return project;
    }

    /// <summary>
    /// 打开项目
    /// </summary>
    public Project OpenProject(string projectFilePath)
    {
        var json = File.ReadAllText(projectFilePath);
        currentProject = JsonSerializer.Deserialize<Project>(json);
        projectRoot = Path.GetDirectoryName(projectFilePath);
        return currentProject;
    }

    /// <summary>
    /// 保存项目
    /// </summary>
    public void SaveProject()
    {
        if (currentProject == null) return;

        currentProject.ModifiedAt = DateTime.Now;
        SaveProjectFile(currentProject);
    }

    /// <summary>
    /// 添加文件到项目
    /// </summary>
    public void AddFile(string filePath)
    {
        if (currentProject == null) return;

        var relativePath = Path.GetRelativePath(
            currentProject.ProjectPath, filePath);

        currentProject.Files.Add(new ProjectFile
        {
            FileName = Path.GetFileName(filePath),
            RelativePath = relativePath,
            FileType = Path.GetExtension(filePath),
            ModifiedAt = File.GetLastWriteTime(filePath),
            FileSize = new FileInfo(filePath).Length
        });

        SaveProject();
    }

    private void SaveProjectFile(Project project)
    {
        var json = JsonSerializer.Serialize(project,
            new JsonSerializerOptions { WriteIndented = true });
        var filePath = Path.Combine(
            project.ProjectPath, $"{project.Name}.lcproj");
        File.WriteAllText(filePath, json);
    }
}

17.4 本地工作空间(LocalSolution)

17.4.1 工作空间管理

public class LocalSolution
{
    /// <summary>
    /// 工作空间根目录
    /// </summary>
    public string WorkspacePath { get; set; }

    /// <summary>
    /// 最近打开的项目列表
    /// </summary>
    public List<RecentProject> RecentProjects { get; set; } = new();

    /// <summary>
    /// 用户偏好设置
    /// </summary>
    public UserPreferences Preferences { get; set; } = new();

    /// <summary>
    /// 初始化工作空间
    /// </summary>
    public void Initialize(string basePath)
    {
        WorkspacePath = basePath;

        if (!Directory.Exists(basePath))
        {
            Directory.CreateDirectory(basePath);
        }

        LoadPreferences();
        LoadRecentProjects();
    }

    /// <summary>
    /// 记录最近打开的项目
    /// </summary>
    public void AddRecentProject(string projectPath)
    {
        RecentProjects.RemoveAll(p => p.Path == projectPath);
        RecentProjects.Insert(0, new RecentProject
        {
            Path = projectPath,
            LastOpened = DateTime.Now
        });

        // 只保留最近10个
        if (RecentProjects.Count > 10)
        {
            RecentProjects = RecentProjects.Take(10).ToList();
        }

        SaveRecentProjects();
    }
}

public class RecentProject
{
    public string Path { get; set; }
    public DateTime LastOpened { get; set; }
    public string Name => System.IO.Path.GetFileNameWithoutExtension(Path);
}

public class UserPreferences
{
    public string Theme { get; set; } = "Light";
    public string Language { get; set; } = "zh-CN";
    public int AutoSaveInterval { get; set; } = 300; // 秒
    public bool ShowStartPage { get; set; } = true;
    public int MaxUndoLevels { get; set; } = 100;
    public double DefaultSnapTolerance { get; set; } = 10;
}

17.5 SignalR实时通信

17.5.1 SignalR集成

LightCAD通过SignalR实现客户端与服务端之间的实时通信,支持协同设计场景:

public class CollaborationClient
{
    private HubConnection hubConnection;

    /// <summary>
    /// 连接到协作服务器
    /// </summary>
    public async Task ConnectAsync(string serverUrl, string projectId)
    {
        hubConnection = new HubConnectionBuilder()
            .WithUrl($"{serverUrl}/collaboration?projectId={projectId}")
            .WithAutomaticReconnect()
            .Build();

        // 注册事件处理
        hubConnection.On<string, string>("EntityChanged",
            OnEntityChanged);
        hubConnection.On<string, string>("EntityAdded",
            OnEntityAdded);
        hubConnection.On<string>("EntityDeleted",
            OnEntityDeleted);
        hubConnection.On<string, string>("UserJoined",
            OnUserJoined);
        hubConnection.On<string>("UserLeft",
            OnUserLeft);

        await hubConnection.StartAsync();
    }

    /// <summary>
    /// 通知实体变更
    /// </summary>
    public async Task NotifyEntityChanged(LcEntity entity)
    {
        if (hubConnection?.State == HubConnectionState.Connected)
        {
            var entityData = SerializeEntity(entity);
            await hubConnection.InvokeAsync("EntityChanged",
                entity.Handle.ToString(), entityData);
        }
    }

    /// <summary>
    /// 通知添加实体
    /// </summary>
    public async Task NotifyEntityAdded(LcEntity entity)
    {
        if (hubConnection?.State == HubConnectionState.Connected)
        {
            var entityData = SerializeEntity(entity);
            await hubConnection.InvokeAsync("EntityAdded",
                entity.Handle.ToString(), entityData);
        }
    }

    private void OnEntityChanged(string handle, string data)
    {
        // 接收其他用户的实体变更
        var entity = DeserializeEntity(data);
        DocumentManager.Current.UpdateEntity(long.Parse(handle), entity);
    }

    private void OnEntityAdded(string handle, string data)
    {
        var entity = DeserializeEntity(data);
        DocumentManager.Current.AddEntity(entity);
    }

    private void OnEntityDeleted(string handle)
    {
        DocumentManager.Current.RemoveEntity(long.Parse(handle));
    }
}

17.6 本章小结

本章介绍了LightCAD的数据库操作和项目管理功能。DBHelper和DBUtility提供了通用的数据库访问能力,支持实体数据的持久化存储。PrjManager实现了完整的项目生命周期管理,包括创建、打开、保存项目以及文件组织。LocalSolution管理本地工作空间和用户偏好设置。SignalR集成为多人协同设计场景提供了实时通信能力。


上一章第十六章:命令与操作系统

下一章第十八章:标注与文本系统