65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (8投票s)

2010年3月8日

CPOL

4分钟阅读

viewsIcon

44526

downloadIcon

1709

自动化数据库、表、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 控件的映射。

为什么不尝试自动完成所有这些步骤?这很辛苦,不是吗?

我已经自动完成了所有这些步骤,您只需要负责创建类和映射列表。让我们看看它是如何工作的。

main.jpg

  • 您创建一个 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();
    }
}

类创建中的重要步骤是(这里的魔力在于)

  1. 类继承自 SQLBase(始终添加 ID)。
  2. 类需要一个空构造函数。
  3. 在构造函数中,初始化字段。
  4. 添加将用于创建表和字段的描述。

正如您所见,目前我添加了许多类型和可为空的值。

第一部分:类和数据库

如何工作

创建一个窗体或类,然后在其中添加 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 控件和类

如何工作

现在您需要创建一个映射列表。假设有一个窗体,如

app.jpg

我们可以轻松地编写以下内容

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 月。
© . All rights reserved.