在基于List数据结构的简易数据库功能实现(C#.NetCore3.1)的基础上进一步整合并做出延申,现需求可以分为以下几点:
- 在内存中存储和管理数据,而不是使用数据库。
- 能够在特定日期范围内检索数据。
- 当新数据添加到内存数据库时,如果已打开显示数据的窗口,则自动更新显示。
- 按日期将数据存储在不同的文件中,每天一个文件。
解决问题的思路:
- 创建一个MemoryDatabase类,用于在内存中管理数据。在这个类中,实现数据的增删改查功能。可以使用一个List集合来存储Student对象。同时,可以实现一个事件,用于在添加新数据时通知其他窗体。
- 在MemoryDatabase类中实现一个方法,用于根据指定的日期范围从文件中加载数据。可以使用日期循环并检查文件是否存在,然后将这些文件中的数据合并到一个列表中。
- 创建一个名为DateRangeForm的子窗体,用于显示特定日期范围内的数据。在这个窗体中,订阅MemoryDatabase类的事件,以便在添加新数据时自动更新显示。
- 在MemoryDatabase类中实现一个方法,用于将内存中的数据保存到文件。可以根据Student对象的日期属性将数据分组,并为每个分组创建一个单独的文件。文件名可以使用日期作为后缀,例如Student20230329、Student20230330等。
以下是代码示例:
- 首先,创建Student类:
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public DateTime Date { get; set; }
}
- 接下来,创建MemoryDatabase类,实现数据的增删改查功能:
public class MemoryDatabase
{
private List<Student> _students;
public MemoryDatabase()
{
_students = new List<Student>();
}
// 定义一个StudentAdded事件
public event EventHandler<StudentEventArgs> StudentAdded;
// 添加一个学生,并触发StudentAdded事件
public void AddStudent(Student student)
{
_students.Add(student);
OnStudentAdded(student);
SaveData();
}
// 触发StudentAdded事件
protected virtual void OnStudentAdded(Student student)
{
StudentAdded?.Invoke(this, new StudentEventArgs(student));
}
// 根据给定的起始和结束日期加载数据
public List<Student> LoadDataInRange(DateTime startDate, DateTime endDate)
{
List<Student> studentsInRange = new List<Student>();
for (DateTime currentDate = startDate; currentDate <= endDate; currentDate = currentDate.AddDays(1))
{
string dateString = currentDate.ToString("yyyyMMdd");
string fileName = $"Student{dateString}.json";
if (File.Exists(fileName))
{
string jsonData = File.ReadAllText(fileName);
var dailyStudents = JsonConvert.DeserializeObject<List<Student>>(jsonData);
studentsInRange.AddRange(dailyStudents);
}
}
return studentsInRange;
}
// 保存数据到文件
private void SaveData()
{
// 将数据根据日期分组
var groupedStudents = _students.GroupBy(s => s.Date.Date);
// 为每个分组的数据创建一个文件
foreach (var group in groupedStudents)
{
string dateString = group.Key.ToString("yyyyMMdd");
string fileName = $"Student{dateString}.json";
string jsonData = JsonConvert.SerializeObject(group.ToList());
File.WriteAllText(fileName, jsonData);
}
}
}
- 创建StudentEventArgs类,用于在事件中传递Student对象:
public class StudentEventArgs : EventArgs
{
public Student Student { get; private set; }
public StudentEventArgs(Student student)
{
Student = student;
}
}
- 在主窗体中,添加一个按钮loadDataRangeButton,用于打开DateRangeForm窗体:
public partial class MainForm : Form
{
private MemoryDatabase _memoryDatabase;
public MainForm()
{
InitializeComponent();
_memoryDatabase = new MemoryDatabase();
}
// 点击按钮时打开DateRangeForm窗体
private void LoadDataRangeButton_Click(object sender, EventArgs e)
{
using (var dateRangeForm = new DateRangeForm(_memoryDatabase))
{
dateRangeForm.ShowDialog();
}
}
}
- 创建DateRangeForm窗体,包括两个DateTimePicker控件(startDatePicker和endDatePicker),一个DataGridView控件(dataRangeDataGridView)和两个按钮(loadDataButton和loadRecentDataButton):
public partial class DateRangeForm : Form
{
private MemoryDatabase _memoryDatabase;
public DateRangeForm(MemoryDatabase memoryDatabase)
{
InitializeComponent();
_memoryDatabase = memoryDatabase;
// 订阅MemoryDatabase的StudentAdded事件
_memoryDatabase.StudentAdded += MemoryDatabase_StudentAdded;
}
// 当StudentAdded事件触发时,重新加载数据
private void MemoryDatabase_StudentAdded(object sender, StudentEventArgs e)
{
DateTime startDate = startDatePicker.Value.Date;
DateTime endDate = endDatePicker.Value.Date;
// 如果添加的学生在当前显示的日期范围内,则重新加载数据
if (e.Student.Date >= startDate && e.Student.Date <= endDate)
{
var studentsInRange = _memoryDatabase.LoadDataInRange(startDate, endDate);
SetDataRangeDataGridViewDataSource(studentsInRange);
}
}
// 设置DataGridView的数据源
private void SetDataRangeDataGridViewDataSource(IList<Student> students)
{
dataRangeDataGridView.DataSource = new BindingList<Student>(students);
}
// 点击加载数据按钮时,根据选择的日期范围加载数据
private void LoadDataButton_Click(object sender, EventArgs e)
{
DateTime startDate = startDatePicker.Value.Date;
DateTime endDate = endDatePicker.Value.Date;
var studentsInRange = _memoryDatabase.LoadDataInRange(startDate, endDate);
SetDataRangeDataGridViewDataSource(studentsInRange);
}
// 点击加载最近数据按钮时,加载最近时间段的数据
private void LoadRecentDataButton_Click(object sender, EventArgs e)
{
LoadRecentData();
}
// 加载最近时间段的数据,并更新日期选择器的值
private void LoadRecentData()
{
DateTime currentDate = DateTime.Now;
DateTime startDate = currentDate.AddDays(-_memoryDatabase.MaxDaysToSearchBack);
DateTime endDate = currentDate;
var studentsInRange = _memoryDatabase.LoadDataInRange(startDate, endDate);
SetDataRangeDataGridViewDataSource(studentsInRange);
startDatePicker.Value = startDate;
endDatePicker.Value = endDate;
}
}
这是一个完整的代码示例。在主窗体中,用户可以点击一个按钮来打开DateRangeForm
窗体。在DateRangeForm
窗体中,用户可以选择一个日期范围并加载数据,也可以一键加载最近时间段的数据。当添加新数据时,如果DateRangeForm
窗体处于打开状态并且新添加的数据在当前显示的日期范围内,数据将自动显示在dataGridView
中。
在主窗体中,我们可以添加一个按钮和一些输入控件(例如,文本框和日期选择器),以便用户可以向数据库中添加新的学生数据。以下是一个简单示例:
在MainForm设计视图中,添加以下控件:
- 一个名为addStudentButton的按钮。
- 三个名为idTextBox、nameTextBox和ageTextBox的文本框,用于输入学生的ID、姓名和年龄。
- 一个名为datePicker的日期选择器,用于选择学生的日期。
为addStudentButton的Click事件添加一个事件处理程序:
private void AddStudentButton_Click(object sender, EventArgs e)
{
// 从输入控件获取学生信息
int id = int.Parse(idTextBox.Text);
string name = nameTextBox.Text;
int age = int.Parse(ageTextBox.Text);
DateTime date = datePicker.Value;
// 创建一个新的Student对象
Student newStudent = new Student { Id = id, Name = name, Age = age, Date = date };
// 将新学生添加到内存数据库中
_memoryDatabase.AddStudent(newStudent);
// 清空输入控件的值以便再次输入
idTextBox.Clear();
nameTextBox.Clear();
ageTextBox.Clear();
}
现在,当用户在主窗体中输入学生信息并点击“添加学生”按钮时,新的学生数据将被添加到内存数据库中。同时,如果DateRangeForm窗体处于打开状态并且新添加的学生数据在当前显示的日期范围内,该数据将自动显示在dataGridView中。
以下运行示例图片:
loadRecentData
loadData