WPF 自动映射到数据库 (Access 07 版)






4.89/5 (8投票s)
自动化数据库、表、SUID 操作的创建,以及 WPF 到类的简单映射。
摘要
该想法是创建一个自动化的 DAL 和自动化的映射,该映射从控件创建存储、表、SUID(Select、Update 等)以及 WPF 映射,反之亦然。
必备组件
- Visual Studio 2008 SP1
- WPF Toolkit 2010 年 2 月发布,仅适用于
DatePicker
控件 - MS Access 2007,但非必需
引言
当您想要创建一个应用程序来存储任何类型的信息时,您会勾勒出您想要存储的信息,定义一个类及其子类。
现在假设您想创建一个可以适应多种数据源(SQL Server、Access、MySQL 等)的 DAL(数据访问层)。那么您需要
- 创建数据库。
- 创建表。
- 创建标准查询。
- 创建将值从类传递到查询的方法。
- 创建从类值到 WPF 控件的映射。
为什么不尝试自动完成所有这些步骤?这很辛苦,不是吗?
我已经自动完成了所有这些步骤,您只需要负责创建类和映射列表。让我们看看它是如何工作的。
- 您创建一个 WPF 窗体
- 创建实例并配置映射类
- 引擎将窗体转换为类
- 为您的应用程序创建业务逻辑类
- 实例化的类由 DAL 管理
- 引擎管理 DAL
类
首先,我创建了一个基本的 Address
类和一个主类 User
,其中包含一个 Address
对象
public enum Countries
{
None,Spain,UK,USA
}
[Description("Addresses")]
public class Address : SQLBase
{
[Description("Street")]
public String Street;
[Description("Number")]
public Int32 Number;
public Address() { Street = String.Empty; Number = 0; }
}
[Description("Users")]
public class User : SQLBase
{
[Description("Name")]
public String Name;
[Description("Age")]
public Int32? Age;
[Description("Birth")]
public DateTime Birth;
[Description("Country")]
public Countries Country;
[Description("Address")]
public Address Address;
[Description("Active")]
public Boolean Active;
[Description("Salary")]
public Single Salary;
[Description("Photo")]
public Bitmap Photo;
public User()
{
Name = String.Empty; Birth = new DateTime(1900, 1, 1); Age = -1;
Country = Countries.None; Photo = new Bitmap(1, 1); Address = new Address();
}
}
类创建中的重要步骤是(这里的魔力在于)
- 类继承自
SQLBase
(始终添加 ID)。 - 类需要一个空构造函数。
- 在构造函数中,初始化字段。
- 添加将用于创建表和字段的描述。
正如您所见,目前我添加了许多类型和可为空的值。
第一部分:类和数据库
如何工作
创建一个窗体或类,然后在其中添加 ACCESS
类的实例,并带有文件和路径的设置或字符串
access = new ACCESS(Properties.Settings.Default.FileName,
Properties.Settings.Default.Path);
创建和删除数据库
这些步骤很简单,我在窗体中添加了设置
access.DeleteDB();
access.CreateDB();
创建表定义
这些方法是通用的,因此如果您定义了良好的类,您将自动获得表。在我们的例子中,要工作的类是 User
,所以
access.CreateDefinition<User>();
添加项
现在,如果您实例化类,您可以轻松地将其插入数据库
User Victoria = new User()
{
Name = "Victoria",
Age = 20,
Country = Countries.Spain,
Birth = new DateTime(1980, 1, 1),
Active = true,
Salary = 1200.24F,
Address = new Address() { Number = 24, Street = "6th Avenue" }
};
access.Add(Victoria);
//Add a List of Users
List<User> users = new List<User>()
{
new User() { Name = "John", Age = 32, Country = Countries.UK,
Birth=new DateTime(1965,2,3), Active = true, Salary = 900.31F,
Address = new Address() { Number = 5, Street = "Brighton Ave."}
},
new User() { Name = "Malcom", Age = null, Country = Countries.UK,
Birth=new DateTime(1979,4,5), Active = false, Salary = 1000.32F,
Address = new Address() { Number = 7, Street = "London Ave."}
},
new User() { Name = "Victoria", Age = 19, Country = Countries.Spain,
Birth=new DateTime(1954,6,7), Active = true, Salary = 1200.2F,
Address = new Address() { Number = 24, Street = "Sea Road" }
}
};
access.Add(users);
正如您所见,您不必担心 ID,系统会管理它们。
检索项
目前,我已创建
- 检索所有
List<User> allusers = access.SelectAll<User>();
List<User> someusers = access.SelectWhere<User> ("Name <>" ,"Victoria");
更新和删除项
如果您有一个已检索的数据库实例,您可以更新或删除它
Victoria = access.SelectWhere<User>("Name =", "Victoria").First();
Victoria.Age = 21; Victoria.Country = Countries.UK; Victoria.Address.Number = 10;
Victoria.Photo = Bitmap.FromFile(Environment.CurrentDirectory +
@"\images\example.png", true) as Bitmap;
access.Update(Victoria);
access.Delete(Victoria);
现在它没有 ID,所以您可以再次添加它
access.Add(Victoria);
您可以按字段更新
access.UpdateBy(Victoria,Victoria.Name);
同样的操作也实现了对项目列表的处理。
第二部分:WPF 控件和类
如何工作
现在您需要创建一个映射列表。假设有一个窗体,如
我们可以轻松地编写以下内容
mapping = new List<ControlBind>();
mapping.CustomAdd(C1_Name,TextBox.TextProperty,"Name");
mapping.CustomAdd(C2_Age,TextBox.TextProperty,"Age");
mapping.CustomAdd(C3_Birth,DatePicker.SelectedDateProperty,"Birth");
mapping.CustomAdd(C4_Country,ComboBox.SelectedItemProperty,"Country");
mapping.CustomAdd(C5_Status,CheckBox.IsCheckedProperty,"Active");
mapping.CustomAdd(C6_Salary,TextBox.TextProperty,"Salary");
mapping.CustomAdd(C7_Photo,System.Windows.Controls.Image.SourceProperty,"Photo");
mapping.CustomAdd(C8_Street,TextBox.TextProperty,"Address.Street");
mapping.CustomAdd(C9_Number,TextBox.TextProperty,"Address.Number");
mapping.CustomAdd(C10_ID,TextBox.TextProperty,"ID");
对于枚举,我将其绑定为
C4_Country.ItemsSource = Enum.GetValues(typeof(WPFBusiness.Countries));
C4_Country.SelectedIndex = 0;
管理项
现在我们可以使用第一部分和以下方法
mapping.GetfromMapping<t>()
mapping.SetfromMapping<t>(T item);
使用示例
private void B_SAdd_Click(object sender, RoutedEventArgs e)
{
access.Add(mapping.GetfromMapping<User>());
}
要检索信息,例如,获取所有信息
Int32 idx = 0;
List<Users><user> allusers = null;
private void B_NAll_Click(object sender, RoutedEventArgs e)
{
allusers = access.SelectAll<user>();
mapping.SetfromMapping(allusers[idx]);
}
它将自动填充控件。例如,进行导航
private void B_NNext_Click(object sender, RoutedEventArgs e)
{
if (allusers != null)
{
if (++idx > allusers.Count - 1)
idx = 0;
mapping.SetfromMapping(allusers[idx]);
}
}
private void B_NPrevious_Click(object sender, RoutedEventArgs e)
{
if (allusers != null)
{
if (--idx ;lt& 0)
idx = allusers.Count-1;
mapping.SetfromMapping(allusers[idx]);
}
}
第三部分:子类
如何工作
假设我们要添加一对多类,例如,一个将附加到用户的任务列表。
定义类
它不继承自 SQLBase
,而是继承自 SQLChild
[Description("Tasks")]
public class Task : SQLChild
{
[Description("Description")]
public String Description;
public Task() { Description = String.Empty; ID = -1; ParentID = -1; }
}
正如您所见,ParentID
将是关系。
定义映射
要在数据库中添加此类记录,我们定义一个类似于 User 映射的映射
taskmapping = new List<controlbind>();
taskmapping.CustomAdd(C11_Task, TextBox.TextProperty, "Description");
为了简化,它只有描述
将子对象添加到父对象
要将对象添加到父对象之一
private void B_TaskAdd_Click(object sender, RoutedEventArgs e)
{
User actual = mapping.GetfromMapping<user>();
if (actual.ID > 0)
{
Task task = taskmapping.GetfromMapping<task>();
access.AddChild<Task,User>(task, actual);
}
ShowTasks(actual);
}
正如您所见,我们将任务分配给实际的用户。
检索父对象的子对象
要检索父对象之一的对象,我们只需指定父对象是谁。
private void ShowTasks(User user)
{
TaskList.Items.Clear();
tasks = access.SelectChilds<Task,User>(user);
tasks.ForEach(t => TaskList.Items.Add(t.Description));
}
就这样。现在您可以定义一对多对象了。
改进
- 能够存储大于 10 KB 的图像
- 能够实现 WPF 中的 N 级嵌套(DAL 部分已完成)
- DAO 方法:更好地将
Recordset
转换为DataTable
历史
- 1.0:首次发布,2010 年 3 月。