• Ilungasoft Framework: 使用视图处理继承关系、Tree结构实体关系映射示例[源码]


    本示例演示基于Ilungasoft Framework实现继承关系和Tree结构的实体。前面的文章已经介绍过,基于Ilungasoft Framework的开发模型使用可调试的视图(Views)代替传统ORM中不可调试的Configuration(例如:XML等各式的配置文件)。前面的Sample2已经介绍了如何使用视图处理一般的OneToMany、ManyToMany关系,本文演示的Sample4,将演示更为复杂的处理两层组织、两层权限、权限可分配给用户或组织这样的模型,包含继承和tree结构,具体演示内容包括:

    1、继承映射(采用一实体一表,不冗余父表字段方式映射);
    2、两种Tree结构映射方式(方式一:单表行冗余,采用用户事务维护tree关系;方式二:单表无冗余,Inner Join + Union);
    3、演示Ilungasoft Framework中的一个新的用于简化处理关联实体的类OneToMany的使用。

    下载

    为了更好的理解示例建议先下载Sample4示例源码

    基本数据表

    数据表非常简单,一共六个,分别为:

    1、Permission(ID,Title,ParentID)- 权限基本信息

    2、User(ID,Name,Age)- 用户基本信息

    3、Group(ID,Title,ParentID)- 组织基本信息

    4、UserGroup(UserID,GroupID)- 用户、组织关联,该表采用单表行冗余(例如:如果添加用户到一个二层组织的纪录,则必须由用户在一个事务中添加用户到父组织的纪录的冗余行,删除是同理)方式存放数据

    5、PermissionOfUser(PermissionID,UserID,Desc)- 赋给用户的权限子类,该表采用不冗余父表字段方式映射继承关系,同时采用单表无冗余(例如:如果将一个二层权限赋给用户,不需要用户添加父权限到用户的冗余纪录)方式存放数据

    6、PermissionOfGroup(PermissionID,GroupID,Desc)- 赋给组织的权限子类,该表采用不冗余父表字段方式映射继承关系,同时采用单表无冗余方式存放数据

    视图

    本文的重点之一就在这里的视图了。

    1、表UserGroup因为采用单表行冗余方式,也就意味着,正反查询直接查询该表就能获得完整的结果,只需要为了方便正反查询的同时获得User或Group的基本信息而建两个简单视图就行,这两个视图分别为:vUserInGroup和vGroupOfUser。

    2、表PermissionOfUser因为采用单表无冗余方式,必须首先建立一个等价于单表行冗余的逻辑视图,视图vPermissionOfUserUnion2就是这样一个逻辑视图。他的SQL代码如下:

    (select UserID, PermissionID from PermissionOfUser)
    UNION (select PU.UserID, P.ID from PermissionOfUser as PU inner join Permission as P on PU.PermissionID = P.ParentID);

    因为这里只演示两层的权限,如果可以有三层,则根据这个规则可以方便构造vPermissionOfUserUnion3,以此类推。

    3、表PermissionOfGroup和视图vPermissionOfGroupUnion2的概念同上。

    4、视图vPermissionOfGroup简单的在vPermissionOfGroupUnion2的基础上,同时获取Permission的基本信息,可以用于通过GroupID查询所有它所拥有的任意层级的权限,反向查询的的视图同理可建。

    5、最后说说一类必须的查询——查询用户真正具有的权限(直接赋给用户的权限Union上用户通过所属组织被赋的权限而继承具有的权限),视图vPermissionOfUserUnionAll首先构造了这张逻辑关联表:

    (SELECT UserGroup.UserID, vPermissionOfGroupUnion2.PermissionID
    FROM UserGroup INNER JOIN vPermissionOfGroupUnion2 ON UserGroup.GroupID = vPermissionOfGroupUnion2.GroupID)
    UNION (select UserID, PermissionID from vPermissionOfUserUnion2);

    而视图vPermissionOfUser简单的为vPermissionOfUserUnionAll扩充Permission的基本信息。

    测试

    好了,构建表和视图的工作至此结束,下面可以来测试一下了。

     1        private void btnLoadGroupsOfUser_Click(object sender, EventArgs e)
     2        {
     3            textBox1.Text = string.Empty;
     4            OneToMany<User, User, UserGroup, vGroupOfUser> o2m = new OneToMany<User, User, UserGroup, vGroupOfUser>("UserID");
     5            o2m.LoadOne("[ID] = @ID"1);
     6            textBox1.Text += SerializeHelper.Serialize(o2m.EntitySelectTypeOne) + "\r\n----\r\n";
     7            textBox1.Text += SerializeHelper.SerializeArray(o2m.SelectMany(nullnull)); //select all many entities
     8        }

     9
    10        private void btnAddUsersToGroup_Click(object sender, EventArgs e)
    11        {
    12            textBox1.Text = string.Empty;
    13            OneToMany<Group, Group, UserGroup, vUserInGroup> o2m = new OneToMany<Group, Group, UserGroup, vUserInGroup>("GroupID");
    14            o2m.LoadOne("[ID] = @ID"2);
    15
    16            //add user with ID 2 to loaded Group
    17            vUserInGroup[] users = o2m.SelectMany("[ID] = @ID"null2);  //no need to set the "[GroupID] = XX" where condition, because o2m auto appended this condition
    18            if (users.Length == 0)
    19            {
    20                UserGroup newUserGroup = o2m.CreateNewEntityMany();
    21                //no need to explictly set newUserGroup.GroupID, because CreateNewEntityMany() auto did this
    22                newUserGroup.UserID = 2;
    23                o2m.InsertMany(newUserGroup);
    24            }

    25
    26            textBox1.Text += SerializeHelper.Serialize(o2m.EntitySelectTypeOne) + "\r\n----\r\n";
    27            textBox1.Text += SerializeHelper.SerializeArray(o2m.SelectMany(nullnull)); //select all many entities
    28        }

    29
    30        private void btnLoadPermissionsOfUser_Click(object sender, EventArgs e)
    31        {
    32            textBox1.Text = string.Empty;
    33            OneToMany<User, User, PermissionOfUser, vPermissionOfUser> o2m = new OneToMany<User, User, PermissionOfUser, vPermissionOfUser>("UserID");
    34            o2m.LoadOne("[ID] = @ID"1);
    35            textBox1.Text += SerializeHelper.Serialize(o2m.EntitySelectTypeOne) + "\r\n----\r\n";
    36            textBox1.Text += SerializeHelper.SerializeArray(o2m.SelectMany(nullnull)); //select all many entities
    37        }

    38
    39        private void btnTestAll_Click(object sender, EventArgs e)
    40        {
    41            textBox1.Text = string.Empty;
    42            
    43            //add a new user
    44            User newUser = DefaultGateway.Create<User>();
    45            newUser.Name = "New User";
    46            newUser.Age = 18;
    47            DefaultGateway.Insert<User>(newUser, "ID");
    48
    49            //create a one to many object and add to group
    50            OneToMany<User, User, UserGroup, vGroupOfUser> o2m = new OneToMany<User, User, UserGroup, vGroupOfUser>("UserID");
    51            o2m.LoadOne("[Name] = @Name""New User");
    52            UserGroup newUserGroup = o2m.CreateNewEntityMany();
    53            newUserGroup.GroupID = 1;
    54            o2m.InsertMany(newUserGroup);
    55
    56            //create a one to many objetc and add some permissions to user
    57            OneToMany<User, User, PermissionOfUser, vPermissionOfUser> o2m2 = new OneToMany<User, User, PermissionOfUser, vPermissionOfUser>("UserID");
    58            o2m2.LoadOne("[ID] = @ID", o2m.EntityCreateTypeOne.ID);
    59            PermissionOfUser newPou = o2m2.CreateNewEntityMany();
    60            newPou.PermissionID = 8;
    61            o2m2.InsertMany(newPou);
    62            newPou.PermissionID = 10;
    63            o2m2.InsertMany(newPou);
    64
    65            //display the user and permissions
    66            textBox1.Text += SerializeHelper.Serialize(o2m2.EntitySelectTypeOne) + "\r\n----\r\n";
    67            textBox1.Text += SerializeHelper.SerializeArray(o2m2.SelectMany(nullnull)); //select all many entities
    68
    69            //delete the added user and all the groups and permissions
    70            DbTransaction tran = DefaultGateway.BeginTransaction();
    71
    72            try
    73            {
    74                o2m.DeleteMany(null, tran);
    75                o2m2.DeleteOne(true, tran);
    76
    77                tran.Commit();
    78            }

    79            catch
    80            {
    81                tran.Rollback();
    82                throw;
    83            }

    84            finally
    85            {
    86                DefaultGateway.CloseTransaction(tran);
    87            }

    88        }

    Sample4是一个WinForm程序(千万别以为Ilungasoft Framework只能用于Web开发,实际上除了Ilungaosft.Framework.Web命名空间,其他功能对WinForm程序是一样适用的,使用也是一样简单),大家可以自行运行,这里仅仅列举一下主要代码。

    简单说明一下OneToMany的功能,OneToMany是一个泛型类,它接受四个泛型参数:
    public class OneToMany<CreateTypeOfOne, SelectTypeOfOne, CreateTypeOfMany, SelectTypeOfMany>
            where CreateTypeOfOne : IEntity
            where SelectTypeOfOne : IEntity
            where CreateTypeOfMany : IEntity
            where SelectTypeOfMany : IEntity;
    前两个参数表示One的类型,后两个表示Many的类型,CreateType表示insert/update是需要使用的实际类型,SelectType则可以是对应于Table的Entity也可以是对应于View的Entity。

    现实数据库中的所有One to Many和Many to Many关系都可以由这个类来表示和简化操作。使用时,构造函数需要传入一个Many表中的外键的字段名称,并且必须先通过LoadOne函数载入One实例,否则其他函数都将不可用。

    好了,本次的实例介绍就到这里,Enjoy!

  • 相关阅读:
    项目常用组建摘记
    How do I resolve the CodeSign error: CSSMERR_TP_NOT_TRUSTED?
    使用wkwebview后,页面返回不刷新的问题
    前端性能监控方案window.performance 调研(转)
    UC浏览器中,设置了position: fixed 的元素会遮挡z-index值更高的同辈元素
    zepto中给不存在的元素设置样式并绑定事件的坑
    js中的路由匹配
    input光标高度问题
    javascript创建css、js,onload触发callback兼容主流浏览器的实现
    js input输入事件兼容性问题
  • 原文地址:https://www.cnblogs.com/teddyma/p/370971.html
Copyright © 2020-2023  润新知