图书馆管理系统开发(C# && Sql Server)

2023-11-19

图书馆管理系统(C/S架构软件)开发

主要步骤

遇见问题

1 主要步骤

1.1 学习主干知识

  • 大概懂得数据库相关sql语法
  • 大概懂得C#语法(C#菜鸟教程)把基础篇看看
  • 大概掌握.Net开发窗口界面(.Net教程)然后可以实战一下项目(VS2022创建窗口界面教程
  • 大概理解三层架构
  • 进入实战进一步理解所学知识

1.2 实战

1.2.1 建立三层架构

在资源管理器里的解决方案添加几个C#类库项目分别对应Model层、DAL层、BLL层。
然后建立项目间的依赖关系。DAL层、UI层、BLL层都引用Model层。BLL层再引用DAL层,UI层再引用BLL层。

1.2.2 创建数据库

根据需求建立对应的数据库、表、视图等。具体数据库设计可以看设计文档。

1.2.3 Model(实体层搭建)

主要就是加入几个属性,例如用户的ID,Name,Password,Type。

namespace Model
{
    public class Mod_UserInfo
    {
        public Mod_UserInfo()
        {
            UserID = "";
            UserName = "";
            UserPWD = "";
            UserType = "reader";
        }
        public string UserID { get; set; }
        public string UserName { get; set; }
        public string UserPWD { get; set; }
        public string UserType { get; set; }
    }
}

1.2.4 DAL层搭建

创建增、删、改、查等简单方法,这个分为两步

  • 建立与数据库的底层连接(这些方法一般直接用现成的例如sqlhelp类等)
    其中比较常调用的是ExecuteNonQuery、ExecuteDataset这两个函数他们的底层也不用深究传几个参数就行。使用方法主要看函数上面的注释。ExecuteNonQuery这个函数主要执行一些不用返回什么值的操作,而ExecuteDataset主要执行一些查询操作可以返回信息列表等。
  • 建立自己相应的执行函数。
public class UserInfo
{
    //新建用户
    public void UserAdd(Model.Mod_UserInfo mod_userInfo)
    {
        //sql执行语句
        string sqlStr = "insert into tUser(userID, userName, userPWD, userType)" +
            "values(@id, @name, @pwd, @type)";
        
        //语句中的参数设置
        SqlParameter[] param = new SqlParameter[]
        {
            new SqlParameter("@id", mod_userInfo.UserID),
            new SqlParameter("@name", mod_userInfo.UserName),
            new SqlParameter("@pwd", mod_userInfo.UserPWD),
            new SqlParameter("@type", mod_userInfo.UserType)
        };

        //执行sql语句
        SqlHelper.ExecuteNonQuery(SqlHelper.connectionString, System.Data.CommandType.Text, sqlStr, param);
    }

    //列出所有用户
    public List<Model.Mod_UserInfo> UserList()
    {
        string sqlStr = "select * from tUser";

        //获取数据集
        DataSet dataset = new DataSet();
        dataset = SqlHelper.ExecuteDataset(SqlHelper.connectionString, System.Data.CommandType.Text, sqlStr);
        
        //定义实体类列队
        List<Model.Mod_UserInfo> userInfos = new List<Model.Mod_UserInfo>();
        
        //将数据集中的数据按行读取输入到实体类列队中
        foreach (DataRow row in dataset.Tables[0].Rows)
        {
            Model.Mod_UserInfo mod_userInfo = new Model.Mod_UserInfo();
            mod_userInfo.UserID = row["userID"].ToString();
            mod_userInfo.UserName = row["userName"].ToString();
            mod_userInfo.UserPWD = row["userPWD"].ToString();
            mod_userInfo.UserType = row["userType"].ToString();
            userInfos.Add(mod_userInfo);
        }

        return userInfos;
    }
    //查询用户
    public Model.Mod_UserInfo UserSearch(string userID)
    {
        string sqlStr = "select * from tUser where userID = @id";

        //设置参数并执行
        DataSet dataset = new DataSet();
        dataset = SqlHelper.ExecuteDataset(SqlHelper.connectionString,
        System.Data.CommandType.Text, sqlStr, new SqlParameter("@id", userID));

        //将获取数据赋给单个实体
        Model.Mod_UserInfo mod_userInfo = new Model.Mod_UserInfo();
        DataRow row = dataset.Tables[0].Rows[0];
        mod_userInfo.UserID = row["userID"].ToString();
        mod_userInfo.UserName = row["userName"].ToString();
        mod_userInfo.UserPWD = row["userPWD"].ToString();
        mod_userInfo.UserType = row["userType"].ToString();

        return mod_userInfo;
    }

    //更新用户
    public void UserUpdate(Model.Mod_UserInfo mod_userInfo)
    {
        string sqlStrSetName = "update tUser set userName = @name where userID = @id";
        string sqlStrSetPWD = "update tUser set userPWD = @pwd where userID = @id";
        string sqlStrSetType = "update tUser set userType = @type where userID = @id";
        
        SqlParameter[] param = new SqlParameter[]
        {
            new SqlParameter("@id", mod_userInfo.UserID),
            new SqlParameter("@name", mod_userInfo.UserName),
            new SqlParameter("@pwd", mod_userInfo.UserPWD),
            new SqlParameter("@type", mod_userInfo.UserType)
        };

        SqlHelper.ExecuteNonQuery(SqlHelper.connectionString, System.Data.CommandType.Text, sqlStrSetName, param);
        SqlHelper.ExecuteNonQuery(SqlHelper.connectionString, System.Data.CommandType.Text, sqlStrSetPWD, param);
        SqlHelper.ExecuteNonQuery(SqlHelper.connectionString, System.Data.CommandType.Text, sqlStrSetType, param);
    }

    //删除用户
    public void UserDelete(string id)
    {
        string sqlStr = "delete from tUser where userID = @id";
        SqlHelper.ExecuteNonQuery(SqlHelper.connectionString, System.Data.CommandType.Text,
            sqlStr, new SqlParameter("@id", id));
    }
}

1.2.5 BLL层搭建

这一层主要对传进来的数据进行逻辑判断的操作

public class BLL_UserInfo
{
    private DAL.UserInfo dal_userInfo = new DAL.UserInfo();
    //增加用户
    public bool UserAdd(Model.Mod_UserInfo mod_userInfo)
    {
        //判断信息是否为空
        if(mod_userInfo != new Model.Mod_UserInfo())
        {
            if(mod_userInfo.UserID.Length == 12)
            {
                dal_userInfo.UserAdd(mod_userInfo);
                return true;
            }
        }
        return false;
    }
    //列举用户
    public List<Model.Mod_UserInfo> UserList()
    {
        List<Model.Mod_UserInfo> userInfos = dal_userInfo.UserList();
        return userInfos;
    }
    //查找用户
    public Model.Mod_UserInfo UserSearch(string id)
    {
        Model.Mod_UserInfo userInfo = dal_userInfo.UserSearch(id);
        return userInfo;
    }
    //修改用户
    public bool UserUpdate(Model.Mod_UserInfo mod_userInfo)
    {
        if (mod_userInfo != new Model.Mod_UserInfo())
        {
            if (mod_userInfo.UserID.Length == 12)
            {
                dal_userInfo.UserUpdate(mod_userInfo);
                return true;
            }
        }
        return false;
    }
    //删除用户
    public void UserDelete(Model.Mod_UserInfo mod_userInfo)
    {
        dal_userInfo.UserDelete(mod_userInfo.UserID);
    }
    //登录用户
    public bool UserSignIn(Model.Mod_UserInfo mod_userInfo)
    {
        //获取数据库中用户信息列表
        List<Model.Mod_UserInfo> userInfos = UserList();

        //判断是否符合登录标准(需要root用户)
        foreach (Model.Mod_UserInfo userInfo in userInfos)
        {
            if (mod_userInfo.UserID.Equals(userInfo.UserID) && 
                mod_userInfo.UserPWD.Equals(userInfo.UserPWD) &&
                mod_userInfo.UserType.Equals("root"))
            { 
                return true;
            }
        }
        return false;
    }
}

1.2.6 UI层搭建

这一层主要是与用户的交互,以登录界面的设计为例。

//登录窗口类
public partial class FormSignIn : System.Windows.Forms.Form
{
    public FormSignIn()
    {
        InitializeComponent();
    }
    private void FormSignIn_Load(object sender, EventArgs e)
    {

    }
    
    //登录按钮触发事件
    private void btnSignIn_Click(object sender, EventArgs e)
    {
        Model.Mod_UserInfo mod_userInfo = new Model.Mod_UserInfo();
        BLL.BLL_UserInfo bll_userInfo = new BLL.BLL_UserInfo();

        //获取用户输入信息
        mod_userInfo.UserID = textBoxUserID.Text;
        mod_userInfo.UserPWD = textBoxUserPWD.Text;
        if(chkBoxReader.Checked )
        {
            mod_userInfo.UserType = "reader";
        }
        else
        {
            mod_userInfo.UserType = "root";
        }

        //传给bll层判断是否符合
        if (bll_userInfo.UserSignIn(mod_userInfo))
        {
            this.DialogResult = DialogResult.OK;
        }
        else
        {
            MessageBox.Show("ID or PassWord wrong.", "Wrong");
        }
    }

    //复选框触发事件(不能同时选root和reader)
    private void chkBoxRoot_CheckedChanged(object sender, EventArgs e)
    {
        if (chkBoxRoot.Checked) { chkBoxReader.Checked = false; }
        else { chkBoxReader.Checked = true; }
    }

    private void chkBoxReader_CheckedChanged(object sender, EventArgs e)
    {
        if (chkBoxReader.Checked) { chkBoxRoot.Checked = false; }
        else { chkBoxRoot.Checked = true; }
    }
}

2 遇见问题

2.1 Windows上.Net开发环境搭建

在搭建.Net开发环境时主要遇到VS2022中无法加载进入桌面应用项目。右键资源管理器选择手动加载时报错"无法找到 .Net SDK,请确保已安装此项目的’global.json’中指定的版本与所安装的版本一致"

根据“找不到 .Net SDK”,先找到"C:\Program Files\dotnet"这个安装 .Net SDK 的地方确保已安装 .Net 。同时打开sdk文件夹如果没有6.0或以上的版本,先安装 .Net 。

如果已有.Net可以打开cmd窗口使用

dotnet info

打印.Net相关信息可能会显示Program Files(X86)的 .Net,这时去改一下环境变量把(X86)的dotnet路径删掉。添加"Program Files/dotnet"这时再打印下就会改用64位的 .Net。

然后还有版本可能是最新的可以通过

dotnet --version

查询当前使用的版本。然后通过global.json进行修改成自己需要的版本。如

dotnet new globaljson --sdk-version 3.1.100

可以把当前使用版本调整为3.1。

2.2 与数据库进行连接时遇到问题

  • 方法一:先建立sqlconnection这是个类对象,然后对它的属性填入自己连接的数据库信息。而这个类需要导入一个必要的NuGet包"System.Data.SqlClient"。导入方法就是点击菜单栏的项目,然后有一个导入NuGet包,再浏览搜索这个名字,下载就行。
  • 方法二:这个其实是建立再方法一上的,只不过只需要定义一个连接字符串
public static string connectionString = "Data Source=127.0.0.1;Initial Catalog=dbLibrary;User ID=sa;Password=123;";

再调用"SqlConnection(connectionString)"这个函数就行了。这其实就又回到方法一。

2.3 UI层设计时实现主窗口内多个窗口的切换效果

首先需要再主窗口加入panel面板,然后再在面板内添加窗体控件(注意不是窗体)。可以先设计好子窗体控件然后在运行时将它加入主窗口的面板处。

//主窗口加载程序
private void FormMain_Load(object sender, EventArgs e)
{
    //向主窗口增加一个窗口控件,使主窗口内能够切换多个小窗口
    ControlWin_ListUserInfo formListUserInfo = new ControlWin_ListUserInfo();
    panWin.Controls.Add(formListUserInfo);
}

2.4 获取控件

获取子窗体控件里的控件也十分重要,这时需要用到pannel.Controls或者form.Controls等控件集合属性。将他们的集合遍历一下就可以了。

//获取窗体或面板里的控件
private Control? GetControl(Control.ControlCollection controlCollection)
{
    foreach (Control control in controlCollection)
    {
        //获取控件里的控件
        if (control.Controls.Count != 0)
            return GetControl(control.Controls);
        else
            return control;
    }
    return null;
}

2.5 登录窗口与主窗口运行顺序

在winform项目中程序一般在主函数开始执行后就会添加一个窗口的线程(就是无限循环),这是如果你有一个登录窗口和一个主窗口,程序会先进入登录。这时,如果想关掉这个窗口

this.Close();

那整个程序就关掉了,无法再进入主窗口。我的做法是先让登录窗口作为一个对话框显示,登录成功后,让对话框改变一个值,主程序就判断该值,如果该值为真,就开始主窗口的线程。

static void Main()
{
    FormSignIn formSignIn = new FormSignIn();
                
    if (formSignIn.ShowDialog() == DialogResult.OK)
    {
        Application.Run(new FormMain());
    }
    else
    {
        return;
    }
}

3 项目地址

GitHub地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图书馆管理系统开发(C# && Sql Server) 的相关文章

  • 是否可以根据 QSlider 的位置来改变其手柄的颜色?

    我非常清楚如何通过样式表自定义 QSlider 但我想知道是否可以执行以下操作 我希望滑块的手柄从蓝色变为黄色 当设置在左侧时 它是蓝色的 设置在左侧时 它是蓝色的 当你将它向右移动时 它会出现从蓝色到黄色的渐变 如果可以通过样式表 如何实
  • 数字或货币的字符串格式?

    我需要为每个千给出逗号 所以我用了DataFormatString 0 它运行良好 但当值为0 它正在显示 00 我只想只显示 0 我们怎样才能做到这一点 DataFormatString 0 C0 这将格式化为小数点后 0 位的货币 Da
  • 异步提交或回滚事务范围

    正如许多人所知 TransactionScope当async await Net 中引入了模式 如果我们尝试使用一些它们就会损坏await在事务范围内调用 现在这个问题已经解决了 感谢范围构造函数选项 a 17527759 1178314
  • Qt:更改 Mac OS X 上的应用程序 QMenuBar 内容

    我的应用程序对多个 页面 使用 QTabWidget 其中顶级菜单根据用户所在的页面而变化 我的问题是 尝试重新创建菜单栏的内容会导致严重的显示问题 它在除 Mac OS X 之外的所有平台上按预期使用第一种和第三种样式 尚未测试第二种 但
  • 输出 objdump -t 的输出中的“.hidden”是什么意思?

    Example objdump Logger cpp o t 00000000 g F text 00000000 hidden sti 10 Logger cpp 0b2ae32b 这意味着符号的可见性被隐藏 https develope
  • 获取枚举实例的名称[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 假设我有这个枚举 public enum MyEnum ValueOne 1 ValueTwo 2 ValueThree 3 然后
  • 是否可以将 long long 返回值分配给 int64_t 而不会丢失 64 位机器中的精度?

    我已经实现了以下代码 include
  • 如何使用c#/VB.NET在word中插入书签

    我正在尝试使用 C 在 Word 文档中添加书签 但它不起作用 而且我在 msdn 文档和互联网上都找不到任何帮助 这就是我正在尝试做的事情 我正在阅读 Word 文档 然后在该文档中搜索关键字 然后将该文本转换为超链接 效果很好 现在 我
  • 如何使用 Unity 动态注册通用类?

    我有一个包含很多类 300 和 BaseClass 的程序集 我想用接口注册一个泛型类 统一后 您必须在 Name如果你想解析接口的对象数组 我想要一个对象数组主视图模型自动地 有没有办法通过反射来自动执行此操作 有什么建议么 示例 伪 p
  • 使用迭代器遍历 boost::ublas 矩阵

    我只是想从头到尾遍历一个矩阵 触及每个元素 然而 我发现升压矩阵没有一个迭代器 而是有两个迭代器 而且我无法弄清楚如何使它们工作以便您可以遍历整个矩阵 typedef boost numeric ublas matrix
  • 将 boost::iostreams::mapped_file_source 与 std::multimap 一起使用

    我有相当大量的数据需要分析 每个文件大约有 5gig 每个文件的格式如下 xxxxx yyyyy 键和值都可以重复 但键是按升序排列的 我正在尝试使用内存映射文件来实现此目的 然后找到所需的键并使用它们 这是我写的 if data file
  • 将图像添加到 ASP.Net 中的单选按钮列表

    我正在尝试将图像添加到单选按钮列表控件 但它不起作用 我试过这个 RadioButtonList2 Items Add new ListItem String Format src Colors Dallas 625527 1 1 png
  • 找到两个值的平均值的正确方法是什么?

    我最近了解到整数溢出是 C 中的未定义行为 附带问题 C 中也是 UB 吗 在 C 编程中 您通常需要求两个值的平均值a and b 然而做 a b 2可能会导致溢出和未定义的行为 所以我的问题是 找到两个值的平均值的正确方法是什么a an
  • 无法在 Visual Studio Code 的 C# 输出上键入任何内容

    所以我试图在 vscode 上运行一个非常基本的 C 程序 代码如下 using System namespace HelloWorld class Program static void Main string args string N
  • Visual Studio 扩展找不到所需的程序集

    我为 Visual Studio 2013 编写了一个扩展 因为该死的组合框错误 https stackoverflow com questions 7800032 cancel combobox selection in wpf with
  • MSVC如何在编译期间输出一些内容到“输出”窗口

    有时我看到某些项目在编译期间向输出写入一些内容 在MSVC 中如何实现 thanks use pragma message e g define MESSAGE t message FILE STRINGXXX LINE t define
  • timeval_subtract 解释

    使用 timeval subtract 函数来查找两个 struct timeval 类型之间经过的时间 有人可以解释一下用于 通过更新 y 执行后续减法的进位 和其他部分的目的和逐步数学吗 我了解该函数的目的以及如何在程序中实现它 但我想
  • 如何在 C# 中使用 Selenium WebDriver 获取当前窗口的 URL?

    在我的应用程序中 登录时 它会导航到另一个页面 现在我需要在 selenium C 中使用 WebDriver 获取新的 URL 我找不到任何函数来执行此操作 我努力了driver Url driver getLocation and dr
  • 复杂对象上的 GroupBy(例如 List

    Using GroupBy and Count gt 1我试图在列表中查找我的类的重复实例 该类看起来像这样 public class SampleObject public string Id public IEnumerable
  • 同时使用多个控制台

    是否有捷径可寻 我现在仅使用控制台测试我的网络应用程序 最好的办法是从一个项目中拥有多个控制台 然后按一下 立即调试 菜单项 我可以像过去一样使用多个项目 但这似乎很笨拙 理想情况下 我可以启动多个控制台实例 从同一线程运行很好 并且让它们

随机推荐

  • Shell中的算术运算

    let expr bc都是在Bash shell环境中进行数学运算时我们会用到的工具 一 整数运算 let 当使用let时 变量名之前不能再添加 用法 var1 2 var2 3 let result var1 var2 echo resu
  • 一文搞懂积分不等式证明(积分证明题总结笔记3/3)

    积分证明题是考研中难度较大的板块 很多学弟学妹们希望我出一篇总结文章 故作本文 希望对大家有所帮助 本文所涉及题目 均是来自市面上常见题册 李林880 张宇1000题 汤家凤1800等 由于内容较多 故分为三部分 等式证明 点击进入 由积分
  • Qt 绘图设备,QPixmap 和QImage 相互转化

    Qt的绘图系统允许使用相同的API在屏幕和其他打印设备上进行绘制 整个绘图系统基于 QPainter QPainterDevice 和 QPaintEngine三个类 QPainter用来执行绘制的操作 QPaintDevice是一个二维空
  • ospf和mgre的综合应用

    1 R6为ISP只能配置IP地址 R1 R5的环回为私有网段 首先划分好IP地址 如下图所示 然后对各个环回和接口进行IP配置 如下面所示 对r1 r1 int l0 r1 LoopBack0 ip add 192 168 1 1 24 r
  • Mybatis-plus查看完整执行sql

    Mybatis plus查看完整执行sql application properties 文件 mybatis plus configuration log impl org apache ibatis logging stdout Std
  • Redis-Sentinel(哨兵模式),看这篇就够了哦

    文章目录 简介 启动并初始化Sentinel 初始化Sentinel服务器 替换普通Redis代码为Sentinel的专用代码 初始化 Sentinel 状态 初始化Sentinel监视的主服务器列表 创建连向主服务器的网络连接 获取主服务
  • 二进制兼容与Qt的D指针

    二进制兼容的定义 一个连接到旧版本的动态库的应用程序 无需重新编译就可以用新版本的动态库运行 则这个库被认为是二进制兼容的 一个连接到旧版本的动态库的应用程序 无需修改源码单需要重新编译后可以用新版本的动态库运行 则这个库被认为是源码兼容的
  • java版spring cloud+spring boot 直播电商 社交电子商务平台

    涉及平台 平台管理 包含自营店面 商家端 PC端 手机端 买家平台 PC端 H5 公众号 小程序 APP端 IOS Android 微服务 核心思想 分布式 微服务 云架构 模块化 原子化 持续集成 集群部署 开发模式 代码生成工具 驱动式
  • 【Java 数据结构】单链表与OJ题

    篮球哥温馨提示 编程的同时不要忘记锻炼哦 暮色降临 冲一杯咖啡 目录 1 什么是链表 2 实现一个单向非循环链表 2 1 实现前的约定 2 2 addFirst 方法 2 3 addList 方法 2 4 addIndex 方法 2 5 c
  • SpringBoot 集成积木报表

    前言 积木报表是jeecg的一款开源但代码不开源的一款自定义报表 可以基于 网页灵活调整报表的布局 样式等内容 无需编程 专为企业数据分析 报表制作而设计 降低管理人员汇总制作报表的门槛 解决各类日常管理和 汇报的难题 但是因为代码不开源所
  • SQL 入门的必读好书

    点击蓝色 有关SQL 关注我哟 加个 星标 天天与10000人一起快乐成长 最近 很多朋友来问我 有没有入门 SQL 的好书 与这些朋友聊天发现 大部分人都没有系统学过计算机专业的专修课 有从物流转行的 有从会计专业扩展的 还有从运维行业转
  • 出现“java.sql.SQLException: 无法转换为内部表示”解决方法

    现在 java sql SQLException 无法转换为内部表示 很可能是因为数据库某字段的类型出错了 比如程序将某字段当做Integer类型 而数据库存储又使用另外一种类型 不如String 建议出现这样问题的同行们认真检查一下代码
  • 软件配置管理

    第一章 1 软件配置管理用于控制变化 2 软件配置管理 Software Configuration Management SCM 是指一套管理软件开发和维护过程中所产生的各种中间软件产品的方法和规则 它是控制软件系统演变的学科 3 软件配
  • java8之lambda表达式

    java8 近期 在一个不完全的统计中 java8的普及率已经到达了近80 图 1 相比之前的java版本 下面两个是java8出现带来最大的影响 其一是极大地简化了代码的复杂度尤其是在处理集合以及接口这两个方面 除此之外 java8引入了
  • Linux系统FTP传输协议

    目录 一 FTP传输协议 什么是FTP传输协议 FTP数据连接的两种方式 二 如何使用FTP传输协议 三 设置黑白名单 设置黑名单 设置白名单 一 FTP传输协议 什么是FTP传输协议 FTP协议 文件传输协议 网络上控制文件传输的双向性
  • 中国央行数字货币或比Libra更早发行,考虑让非政府机构参与试点

    中国官员和专家们表示 中国正在测试推出中国首款央行数字货币 CBDC 的多种方式 他们预计私营机构将更多地参与创造政府支持的货币 基于一些领域正在进行的试验 引入 CBDC 的时机已经接近成熟 但与中国央行关系密切的专家们周一表示 Face
  • 区块链教育应用案例_区块链技术在教育领域中的应用研究

    来源 廊坊云报 廊坊日报讯教育对一个国家来说意味着希望 教育行业数字的应用是各行各业发展的基础 只有通过完善的教育体系 才能培育出更加优秀的人才来输送到各个行业 所以说教育领域是一个重要领域 其他重要领域的未来 包括科学 医学 农业 工业和
  • 华为hilens 系统制作

    恢复出厂设置 https support huawei com enterprise zh doc EDOC1100112066 9b0a1fba 长按RST按钮2 3秒 在这个过程中 短按电源按钮后松开 当前面板健康指示灯出现橙色 常亮
  • Debian 12 发布,迄今为止最佳 Linux 版本

    Debian 项目今天发布了 Debian 12 Bookworm 操作系统的最终版本 这是一个重大发布 带来了几个新功能 更新的组件和许多改进 凭借其长期稳定和安全的历史 Debian 12 备受全球开源爱好者的热切期待 这个新版本带来了
  • 图书馆管理系统开发(C# && Sql Server)

    图书馆管理系统 C S架构软件 开发 主要步骤 遇见问题 1 主要步骤 1 1 学习主干知识 大概懂得数据库相关sql语法 大概懂得C 语法 C 菜鸟教程 把基础篇看看 大概掌握 Net开发窗口界面 Net教程 然后可以实战一下项目 VS2