我的KT库之----数据对象

简介:

了解或者认识KT:

http://www.cnblogs.com/kingthy/archive/2011/08/08/2130973.html

在项目中如何使用KT?

KT是一个库,所以将KT的dll文件引用到您的项目上即可使用KT里的函数功能。

本节将介绍大家认识KT库里的数据对象(DbObject)。KT里的数据对象是KT简易ORM框架里的一个对象角色,它存放于在“KT.Framework“下,当你已在你的项目里引用了KT库后,则写下以下代码就可以使用数据对象了。

using KT.Framework;

什么是数据对象

数据对象可用于简单处理数据的存储与交互,如将数据进行实体化处理。KT里的数据对象DbObject对象类似于一个“字典”对象,添加到数据对象里的数据都被放入内部的一个“槽”里进行维护,如以下的代码:

DbObject obj = new DbObject();
obj["name"] = "张三";
obj["age"] = 23;
Console.WriteLine("姓名:{0}", obj["name"]);
Console.WriteLine("年龄:{0}", obj["age"]);

//或者通过SetData/GetData<T>方法设置/获取数据
obj.SetData("name", "李四");
Console.WriteLine("姓名:{0}", obj.GetData<string>("name"));
Console.WriteLine("年龄:{0}", obj.GetData<int>("age"));
Console.Read();

 

扩展数据对象

虽可以直接将数据对象当作一个字典对象使用,但很多场合下我们却是需要将数据进行实体化处理,所以我们需要将数据对象进行扩展。如以下的代码示例:

/// <summary>
/// 用户对象
/// </summary>
public class DbUser : DbObject
{
    public User()
    {

    }
    /// <summary>
    /// 姓名
    /// </summary>
    public string Name
    {
        get
        {
            return this.GetData<string>("Name", null);
        }
        set
        {
            this["Name"] = value;
        }
    }
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age
    {
        get
        {
            return this.GetData<int>("Age", 0);
        }
        set
        {
            this["Age"] = value;
        }
    }
}

 

这样扩展后,我们的数据对象User就是强类型的了,如下面的使用代码示例:

DbUser user = new DbUser();
user.Name = "张三";
user.Age = 12;

 

有时我们的类里需要使用到类内部的“字段”,则我们也可以将“字段”关联到数据对象里,如下面的扩展方法处理

/// <summary>
/// 用户对象
/// </summary>
public class DbUser : DbObject
{
    public DbUser()
    {
        this.AddInternalData("Id", () => this.Id, (o) => this.Id = o.As<int>());
    }
    /// <summary>
    /// 编号
    /// </summary>
    public int Id;

    /// <summary>
    /// 姓名
    /// </summary>
    public string Name
    {
        get
        {
            return this.GetData<string>("Name", null);
        }
        set
        {
            this["Name"] = value;
        }
    }
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age
    {
        get
        {
            return this.GetData<int>("Age", 0);
        }
        set
        {
            this["Age"] = value;
        }
    }
}

我们通过“AddInternalData”方法,将Id字段加入到了数据对象里,这样我们就可以在数据对象里使用”Id”数据了,如下面代码

            DbUser user = new DbUser();
            user["Id"] = 33;
            Console.WriteLine(user.Id);  //输出33
            user.Id = 22;
            Console.WriteLine(user.GetData<int>("Id"));  //输出22

 

 

还有一种情况,有时对一种数据,我们多有种不同的名称,比如“用户名”,有时使用为“name“,有时又为“username“,比如以下两句SQL语句

 

SELECT Name FROM [User]
SELECT B.BookName,U.UserId,U.Name AS UserName FROM [Book] B INNER JOIN [User] U ON U.Id=B.UserId

在第一句SQL语句里,因为只单纯查询用户表,所以可以使用“name”做用户的名称,但在第二句SQL语句里,为了区别用户的数据,又采用了"username”做为用户名数据,对于这种情况,我们也可以在数据对象里进行扩展,如以下示例代码

/// <summary>
/// 用户对象
/// </summary>
public class DbUser : DbObject
{
    public DbUser()
    {
        this.AddInternalData("Id", () => this.Id, (o) => this.Id = o.As<int>());
    }
    /// <summary>
    /// 编号
    /// </summary>
    public int Id;

    /// <summary>
    /// 姓名
    /// </summary>
    public string Name
    {
        get
        {
            return this.GetData<string>("Name", null);
        }
        set
        {
            this["Name"] = value;
        }
    }
    /// <summary>
    /// 年龄
    /// </summary>
    public int Age
    {
        get
        {
            return this.GetData<int>("Age", 0);
        }
        set
        {
            this["Age"] = value;
        }
    }

    protected override bool OnBeforeSetData(string name, object value)
    {
        if ("username".Equals(name, StringComparison.OrdinalIgnoreCase))
        {
            //调用内部的SetDataImp方法,可避免再一次触发OnBeforeSetData方法
            this.SetDataImp("name", value);

            /**
             * 注:以下两种方式都会再一次触发OnBeforeSetData方法,所以尽量不要使用
             * this.SetData("name", value);
             * this.Name = value.As<string>();
            **/
            return false;
        }
        return base.OnBeforeSetData(name, value);
    }
}

 

使用示例

            DbUser user = new DbUser();
            user.Name = "张三";
            Console.WriteLine(user.Name);  //输出"张三"
            user["username"] = "李四";
            Console.WriteLine(user.Name);  //输出"李四"

 

 

 

数据对象的使用

在上面示例代码里,也许会有很多同学都会问“这样的数据对象,看不出它的好处在哪里,并且比直接写一个类结构还更复杂”,是的,直接这样使用数据对象,真的体现不出它的好处在哪里,但如果将数据对象与“数据库”挂上关系,那就可以体现数据对象的好处在哪里了。比如我们的数据库有这样的两个表

 
 

表1:User 用户表

Id int
Name nvarchar(20)
Age int
Phone nvarchar(20)
LocationId int

表2:Location 位置表

Id int
UserId int
City nvarchar(30)
Address nvarchar(200)
Zipcode nvarchar(6)

 

现在我们需要获取User表里的数据,比如有以下的SQL语句

SELECT * FROM [User]

根据上表可以知道,这样的查询语句,将获取到的数据共有5个(Id,Name,Age,Phone,LocationId),但如果将这些数据映射到某个实体类去,并且实现数据的一一对应,那我们就需要定义这5个属性或字段,如下面的类

/// <summary>
/// 用户对象
/// </summary>
public class User 
{
    public User()
    {

    }
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Phone { get; set; }
    public int LocationId { get; set; }
}

 

但假如我们现在在获取用户数据时还需要同时获取用户的地址位置数据,如以下的SQL语句

SELECT U.Id,U.Name,L.City,L.Address,L.Zipcode FROM [User] U INNER JOIN [Location] L ON L.Id=U.Location.Id

 

这条查询语句我们共需要获取Id,Name,City,Address,Zipcode这5个数据,很明显,这里的数据与上面的User类结构是不相同的,也就是如果需要将这条SQL语句映射为类对象,我们又需要建多一个类结构对象。也就是每当我们SQL语句有变化时,我们就需要增加不同的类对象,这样对我们来说是非常麻烦且工作量是非常之大的。

 

如果我们使用数据对象来做数据映射,因为数据对象本来就是一个“字典”对象,所以不管我们的SQL语句如何变化,数据都是进入到数据对象里的“槽”里,再根据“扩展数据对象”反映到对象的“属性”或“字段”里。比如上面两句SQL语句我们都可以将其映射为“扩展数据对象”那段里定义的“DbUser”对象,对于未“扩展”的“Phone,LocationId,City,Address,Zipcode“等数据,我们则可以在需要时通过数据对象的“GetData<T>”方法获取,如下:

var phone = user.GetData<string>("Phone");
var locationId = user.GetData<int>("LocationId");

 

从上面的示例中,我们可以看到DbObject有点类似于DataTable,确切的说应该是像DataRow,只当一个相同的DbObject列表集时,才能说象DataTable。KT也提供了DbObject的扩展方法,通过扩展方法DataTable与List<DbObject>可以互相转换。如下示例:

DataTable new DataTable"name"typeofstring"age"typeofint"张三""李四"var DbUserConsole//输出:2
            Console//输出:张三
            var Console//输出:2
            Console"Name"//输出:张三
本文转自Kingthy博客园博客,原文链接:http://www.cnblogs.com/kingthy/archive/2011/08/24/2152641.html ,如需转载请自行联系原作者
相关文章
|
4月前
|
编译器 Go 开发者
|
4月前
|
缓存 Go
Go引用包版本更新但是被引用的包的子包并没有出现在vendor中的问题和解决方案
文章讨论了在Go模块项目中升级依赖包版本时遇到的子包未出现在vendor目录的问题,并提供了直接删除旧版本引用并重新执行`go mod vendor`的解决方案。
42 0
|
Unix
App Inventor 2 从.aia项目文件中提取.aix拓展包
App Inventor 2 如何从.aia项目文件中提取.aix拓展包,详细的操作步骤。
217 0
App Inventor 2 从.aia项目文件中提取.aix拓展包
python--类-实例-继承中变量的id是否变化
python--类-实例-继承中变量的id是否变化
118 0
【GO】自定义包引用解决方案
【GO】自定义包引用解决方案
114 0
【GO】自定义包引用解决方案
|
程序员 Python
python模块与类库(创建、导入与使用逻辑,子模块,if __name__ ==‘main‘: 语句, __name__,__dict__,__doc__,__file__等)
python模块与类库(创建、导入与使用逻辑,子模块,if __name__ ==‘main‘: 语句, __name__,__dict__,__doc__,__file__等)
258 0
python模块与类库(创建、导入与使用逻辑,子模块,if __name__ ==‘main‘: 语句, __name__,__dict__,__doc__,__file__等)
【7】JAVA---地址App小软件(AddrBusiness.class)(逻辑层)
【7】JAVA---地址App小软件(AddrBusiness.class)(逻辑层)
450 0