C# 使用自定义类+字典+JSON填充数据,脱离真实数据库,实现简单的增删改查和本地存储与读取数据

前言

这个文章将不会用到数据库,另辟蹊径去实现本地的存储与读取,增删改查!~

之前写项目用到的思路,因为是非常小的项目,不想依赖数据库来增删改查,以此避免复杂的数据库环境支持和安装。之前想上网查找有没有代替的方法,现在在网上几乎都是用数据库填充,没有不用数据库的,没办法,只好动手自己写了!

开始之前,容我说明本文章适合的情况:

①适合数据表少的项目。

②适合将数据存储在本地的项目。

③适合不想依赖复杂的数据库环境,同时想拥有存储和增删改查数据的功能的项目。

④不优雅,不聪明,但是很简单粗暴,可以快速实现


基本功能实现的思路

实现思路非常简单:

Dictionary:作为主要数据载体。增删改查在其基础上进行。

自定义类:作为数据表。字典的建立依赖于它。

JSON:用于数据存储与读取。

数据库中的数据表其实就是一个大型的键对值存储,会有一个主键,然后对应着一列数据。

Dictionary的键对值很完美契合我们的需求。

C#中,Dictionary的主要用途是提供快速的基于键值的元素查找。Dictionary的结构一般是这样的: Dictionary<[key], [value]>

Dictionary的描述
1、从一组键(Key)到一组值(Value)的映射,每一个添加项都是由一个值及其相关连的键组成
2、任何键都必须是唯一的
3、键不能为空引用null(VB中的Nothing),若值为引用类型,则可以为空值
4、Key和Value可以是任何类型(string,int,custom class 等)

①我们只需要先自定义一个类。

public class Client//根据自己需要定义类
{
    public string id;//我们的主键
    public string name;
    public string type;
    public string state;
}

②我们再定义一个Dictionary。Dictionary的Key类型是我们主键的类型,而Value内容是我们的自定义的类。

public static Dictionary<string,Client> db=new Dictionary<string,Client>();

③写一个方法,填充数据至控件之中。这里以winform的datagridview填充为例。

注意:datagridview的Column数量要和你自定义类的字段数量一致。

public void DataBind()//填充最新的数据,也可以当做刷新的方法
{
    dataGridView1.Rows.Clear();//清空
    //遍历字典的每一个元素
    foreach (var pair in db)
    {
        //此时RowCount-1的大于字典的Count或者字典内没有数据则可以停止填充
        if (dataGridView1.RowCount - 1 > db.Count||db.Count==0) return;
        //新增行
        int index = dataGridView1.Rows.Add();
        //拿到类数据
        var results = db[pair.Key];
        dataGridView1.Rows[index].Cells[0].Value = results.id;
        dataGridView1.Rows[index].Cells[1].Value = results.name;
        dataGridView1.Rows[index].Cells[2].Value = results.type;
        dataGridView1.Rows[index].Cells[3].Value = results.state;
    }
}

④我们可能要在很多地方调用这个方法,如果会跨线程,请改写成Invoke形式

public void DataBind()//填充最新的数据,也可以当做刷新的方法
{
    if (dataGridView1.InvokeRequired)//跨线程
    {
        //委托
        dataGridView1.Invoke(new EventHandler(delegate
        {
            dataGridView1.Rows.Clear();
            foreach (var pair in db)
            {
                //此时RowCount-1的大于字典的Count或者字典内没有数据则可以停止填充
                if (dataGridView1.RowCount - 1 > db.Count||db.Count==0) return;
                //新增行
                int index = dataGridView1.Rows.Add();
                //拿到类数据
                var results = db[pair.Key];
                dataGridView1.Rows[index].Cells[0].Value = results.id;
                dataGridView1.Rows[index].Cells[1].Value = results.name;
                dataGridView1.Rows[index].Cells[2].Value = results.type;
                dataGridView1.Rows[index].Cells[3].Value = results.state;
            }
        }));
    }
    else//没有跨线程
    {
        dataGridView1.Rows.Clear();
        foreach (var pair in db)
        {
            //此时RowCount-1的大于字典的Count或者字典内没有数据则可以停止填充
            if (dataGridView1.RowCount - 1 > db.Count||db.Count==0) return;
            //新增行
            int index = dataGridView1.Rows.Add();
            //拿到类数据
            var results = db[pair.Key];
            dataGridView1.Rows[index].Cells[0].Value = results.id;
            dataGridView1.Rows[index].Cells[1].Value = results.name;
            dataGridView1.Rows[index].Cells[2].Value = results.type;
            dataGridView1.Rows[index].Cells[3].Value = results.state;
        }
    }
}

我们可以在很多地方调用,增删改一条数据都需要调用这个方法来进行datagridview的即时刷新。接下来就是增删改查的方法实现。

增加的方法很简单,首先New一个我们的自定义类用变量存储起来,将数据填入这个变量下对应的字段,之后就插入字典中,最后刷新。

public void Add()
{
    Client p = new Client
    {
        id = Textbox1.Text,
        name = Textbox2.Text,
        type = Textbox3.Text,
        state = Textbox4.Text
    };
    //先查看有没有重复数据插入
    if(!db.ContainsKey(p.id))
    {
        db.Add(p.id, p);//以id为Key,Dictionary的Key唯一,插入数据
    }
    //重复主键则不能插入
    else
    {
        MessageBox.Show("已存在此数据!请勿重复插入!");
        return;
    }
    DataBind();//调用刷新方法,刷新最新数据
}

演示Demo-增的实现效果图

删除主要是要获取到主键。获取到主键即可删除字典对应的数据。以datagridview为例,就是需要获取用户点击的那一行的索引,从而获得那一行的逐渐数据。

public void Del()
{
    int index = dataGridView1.CurrentRow == null ? -1 : dataGridView1.CurrentRow.Index;//获得当前行
    if (index < 0) return;//如果没点击则返回,防止用户没有选中点击也会执行接下来的代码。
    if (dataGridView1.Rows[index].Cells[1].Value == null) return;//选中行没有数据也返回
    string id = dataGridView1.Rows[index].Cells["Id"].Value.ToString().Trim();//获得当前行的id
    if (db.ContainsKey(id))//字典中有才能删,防止意外情况
    {
        db.Remove(id);//删除字典中的对应值
    }
    DataBind();//调用刷新方法,刷新最新数据
}

演示Demo-删的实现效果图

主要是获取到主键就能获取到信息,将数据传入你想要的位置,进行修改后保存至原来的对应键即可。注意如果是传入新窗口,则要连同数据和主窗口一起传入新窗口中,方便调用刷新代码。

public void UpDate()//改
{
    int index = dataGridView1.CurrentRow == null ? -1 : dataGridView1.CurrentRow.Index;//获得当前行
    if (index < 0) return;//如果没点击则返回,防止用户没有选中点击也会执行接下来的代码。
    if (dataGridView1.Rows[index].Cells[1].Value == null) return;//选中行没有数据也返回
    string id = dataGridView1.Rows[index].Cells["Id"].Value.ToString().Trim();//获得当前行的id
    Client res = new Client();
    if (db.ContainsKey(id))//字典中有才能查和删,防止意外情况
    {
        res = db[id];//获取到对应的数据类
    }
    UpDateForm form=new UpDateForm(res,this);//将数据和主窗口传入新的窗口中
    form.Show();//打开新窗口
}
//改的窗口构造函数代码
Mainform form;//创建主窗口变量
Client res;//创建类实例
public UpDateForm(Client digtal,Mainform mainform)
{
    InitializeComponent();
    res=digtal;//数据传入
    form=mainform;//窗口传入

}
//改窗口保存按钮代码
public void UpDateSave()
{
    //注意主键不能修改
    res.name = Textbox2.Text;
    res.type = Textbox3.Text;
    res.state = Textbox4.Text;
    //覆盖原来的内容
    Mainform.db[res.id]=res;
    form.DataBind();//调用主窗口刷新方法,刷新最新数据
    Close();//修改完关闭窗口
}

演示Demo-改的实现效果图

获取到主键,和相应想查的内容进行遍历字典,以需要过滤的条件进行改变显示表格。与DataBind类似。

以查name为例。

public void Find()
{
    string nameText=TextBox1.Text;//获取name值
    dataGridView1.Rows.Clear();
    //遍历数据库
    foreach (var pair in db)
    {
        if (pair.Value.name == nameText)
        {
            //此时RowCount-1的大于字典的Count或者字典内没有数据则可以停止填充
            if (dataGridView1.RowCount - 1 > db.Count||db.Count==0) return;
            //新增行
            int index = dataGridView1.Rows.Add();
            //拿到类数据
            var results = db[pair.Key];
            dataGridView1.Rows[index].Cells[0].Value = results.id;
            dataGridView1.Rows[index].Cells[1].Value = results.name;
            dataGridView1.Rows[index].Cells[2].Value = results.type;
            dataGridView1.Rows[index].Cells[3].Value = results.state;
        }
    }
    if(dataGridView1.RowCount-1==0)
    {
        DataBind();//没有数据就刷新全部
        MessageBox.Show("没有此数据!");
    }
}

演示Demo-查的实现效果图

以上就基本可以满足代替数据表的需求了,但是始终是存在在程序内的,关闭就消失了,而打开时也会是空白,那么我们接下来就是要把数据存下来,而且在下次打开程序时读取对应的数据,做本地的存储和读取。


本地的存储与读取的实现

这里的灵感来自于《侠客风云传前传》的存档方式,当我过不了关时想修改存档时,我发现他的存档文件是一个txt文件,里面写满了,密密麻麻的JSON语句。

我瞬间悟了,它是每次读取存档,都是将JSON转为实体数据,存储存档就是将实体数据转为JSON写入txt中。

虽然不优雅且粗暴,但是很好用。

这里需要引入一个DLL。

using Newtonsoft.Json;//用于将实体类转为json语句,或者将json语句转为实体类

本地存储

每次存储的时候都是在退出的时候再做存储(如果你想在录入新数据的时候存储,也可以自己改)。

原理也很简单,我们用一个json类,每次退出前,先将目前的字典,一个个输出为一条条json语句,存储起来在本地的某个txt中即可。

将方法写入窗口的Closing方法中。

string path = Application.StartupPath;//获取程序路径
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)//关闭窗体
{

    DialogResult diRes = MessageBox.Show("是否关闭程序?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
    if (diRes == DialogResult.OK)
    {
        if (!File.Exists($"{path}/config/MainSet.txt"))//如果是第一次创建
        {
            StreamWriter sw = new StreamWriter($"{path}/config/MainSet.txt", false);//写入文件,覆盖模式
            //遍历字典
            foreach (var item in db)
            {
                //将实体类转为字符串
                string jsonStr = JsonConvert.SerializeObject(item.Value);
                //写入txt
                sw.WriteLine(jsonStr);
            }
            //关闭
            sw.Close();

        }
        else//改写习惯
        {
            string all = "";
            if (db.Count > 0)
            {    //遍历字典
                foreach (var item in db)
                {
                    string jsonStr = JsonConvert.SerializeObject(item.Value);
                    all += jsonStr + "\n";
                }
            }
            File.WriteAllText($"{path}/config/MainSet.txt", all);
        }
    }
    else//假如用户取消了退出
    {
        e.Cancel = true;//取消退出
        return;//结束方法
    }

}

本地读取

每次读取是在程序打开的时候。我们从我们存储的txt文件中读取所有的JSON语句并转化成实体类存入字典中,并刷新填充datagridview。

将方法写入窗口的Load方法中。

string path = Application.StartupPath;//获取程序路径
private void MainForm_Load(object sender, EventArgs e)
{
    if (File.Exists($"{path}/config/MainSet.txt"))//查找这个文件是否存在
    {
        string[] lines = File.ReadAllLines($"{path}/config/MainSet.txt");//一行行写入一个字符串数组
        for (int i = 0; i < lines.Length; i++)
        {
            Client a = JsonConvert.DeserializeObject<Client>(lines[i]);//每一句都解析成类保存
            string Id = a.id;
            if (!db.ContainsKey(Id))
            {
                db.Add(Id, a);
            }
        }
    }
    DataBind();//填充列表
}

本地存储与读取效果图,成功保留表数据

JSON的txt文件展示,数据就是以这种形式保存下来的(跟侠客风云传前传的存档文件一毛一样,有兴趣的可以去看看)。

结语

好了!到这里已经全部结束了,还望大家多多指教,能帮到大家那是最好的!

你已经是一个脱离数据库的特殊crud选手了!!快来做一个多线程Socket连接程序吧!(不是)

这是博主的项目(- ▽ -)给你们露两手!

猜你喜欢

转载自blog.csdn.net/aa989111337/article/details/128643602
今日推荐