• Ilungasoft Framework中处理有关联关系的实体


    Ilungaosft Framework是Teddy近期发布的开源Web快速开发框架,包括持久层及一系列方便Web开发的组件。本文将在一个新的Sample的基础上,说明基于Ilungasoft Framework开发是如何处理有关联关系的实体。我要再次说明的是,Ilungasoft Framework的设计出发点不是要完全透明的进行ORM,因此,不会自动映射实体关系,以此换来的好处是其完全不需要配置,拥有极大的灵活性和易用性。但是这并不表示,基于Ilungasoft Framework处理实体关系就不方便。本示例就演示了一个非常常见的用户和组、消息的关联关系,涵盖了一对多、多对多的关联情形。

    下载示例源码

    Sample2.zip

    分析

    实际上,Ilungasoft Framework不被设计成一个完全的ORM,而是一个强类型的泛型数据访问接口。因此,基于Ilungasoft Framework开发时,推荐使用视图来描述复杂查询,也推荐采用视图来简化有关联关系的实体访问。

    在本示例中,共涉及四张表:User、Group、UserGroup、Message。大家从名字就能猜测其关系。User表示人员,Group表示组,人员和组是多对多关系,UserGroup就是关联表;而Message的FromUserID和ToUserID则分别和User的ID关联,也就是说,他们的关系是一对多;同时,Group是一个两层的组织结构,也就是说,Group包含下级的Group,通过Group中的字段ParentID来区分——ParentID为0表示顶层Group,否则ParentID为父Group的ID。

    那么,在Ilungasoft Framework方式下,怎样简化处理这样的关联关系呢?没错,就是前面就提到的——视图。只需要建三个视图就能基本满足需求,方便起见,我这里直接列出视图的SQL,要直观的查看关系的话,请打开下载示例中App_Code目录下的mdb文件。

    vUser
    SELECT User.ID, User.Name, User.Gender, User.Salary, UserGroup.GroupID
    FROM UserGroup INNER JOIN [User] ON UserGroup.UserID = User.ID;

    vGroup
    SELECT Group.ID, Group.Title, Group.Description, Group.CreateTime, Group.ParentID, UserGroup.UserID
    FROM [Group] INNER JOIN UserGroup ON Group.ID = UserGroup.GroupID;

    vMessage
    SELECT Message.ID, Message.FromUserID, User.Name AS FromUserName, Message.ToUserID, User_1.Name AS ToUserName, Message.Title, Message.Content, Message.SendTime
    FROM (Message INNER JOIN [User] ON Message.FromUserID = User.ID) INNER JOIN [User] AS User_1 ON Message.ToUserID = User_1.ID;

    我们可以看到:vUser可以用于通过GroupID对User进行查询,vGroup可用于通过UserID查询Group,这就通过逻辑视图将一个多对多关联的三个表,转换为了两对一对多的逻辑视图。而对于,一对多的关系,通过外键字段查询关联关连实体本身就比较自然,不需为关联关系作特别处理,只是我希望查询Message时,能一并获得发送人和接受人的名字,因此,建了vMessage这个视图,这又体现了该方案相对于传统ORM方案的灵活性。

    代码

    那么来看看在代码中如何查询、更新这些表和视图吧(这里就只列出后代查询代码了,具体效果请自行运行示例,实体类代码可以由EntityGen方便生成,这里也就不列举了,和数据库表、视图名称、字段是一一对应的):

      1using System;
      2using System.Data;
      3using System.Data.Common;
      4using System.Configuration;
      5using System.Web;
      6using System.Web.Security;
      7using System.Web.UI;
      8using System.Web.UI.WebControls;
      9using System.Web.UI.WebControls.WebParts;
     10using System.Web.UI.HtmlControls;
     11
     12public partial class _Default : System.Web.UI.Page 
     13{
     14    protected void Page_Load(object sender, EventArgs e)
     15    {
     16        if (!IsPostBack)
     17        {
     18            Entity.Group[] groups = Facade.Select<Entity.Group>("ParentID = 0");
     19            listGroups.DataSource = groups;
     20            listGroups.DataTextField = "Title";
     21            listGroups.DataValueField = "ID";
     22
     23            Entity.User[] users = Facade.SelectAll<Entity.User>();
     24            listUsers.DataSource = users;
     25            listUsers.DataTextField = "Name";
     26            listUsers.DataValueField = "ID";
     27
     28            DataBind();
     29
     30            RefreshSubGroups();
     31        }

     32    }

     33
     34    private void RefreshSubGroups()
     35    {
     36        Entity.Group[] subGroups = Facade.Select<Entity.Group>("ParentID = @ParentID"int.Parse(listGroups.SelectedValue));
     37        Entity.Group[] list = new Entity.Group[subGroups.Length + 1];
     38        Entity.Group allSubGroup = Facade.Create<Entity.Group>();
     39        allSubGroup.Title = "All";
     40        list[0= allSubGroup;
     41        subGroups.CopyTo(list, 1);
     42        listSubGroups.DataSource = list;
     43        listSubGroups.DataTextField = "Title";
     44        listSubGroups.DataValueField = "ID";
     45
     46        listSubGroups.DataBind();
     47    }

     48
     49    protected void btnViewUsersInGroup_Click(object sender, EventArgs e)
     50    {
     51        int selectedSubGroup = int.Parse(listSubGroups.SelectedValue);
     52        Entity.vUser[] usersInGroup = Facade.Select<Entity.vUser>("GroupID = @GroupID", selectedSubGroup > 0 ? selectedSubGroup : int.Parse(listGroups.SelectedValue));
     53        gridView.DataSource = usersInGroup;
     54        DataBind();
     55    }

     56
     57    protected void btnViewGroupsOfUser_Click(object sender, EventArgs e)
     58    {
     59        Entity.vGroup[] groupsOfUser = Facade.Select<Entity.vGroup>("UserID = @UserID"int.Parse(listUsers.SelectedValue));
     60        gridView.DataSource = groupsOfUser;
     61        DataBind();
     62    }

     63
     64    protected void btnViewMessages_Click(object sender, EventArgs e)
     65    {
     66        Entity.vMessage[] messages = Facade.SelectAll<Entity.vMessage>();
     67        gridView.DataSource = messages;
     68        DataBind();
     69    }

     70
     71    protected void btnTestAddUserToGroup_Click(object sender, EventArgs e)
     72    {
     73        Entity.UserGroup[] userGroups = Facade.Select<Entity.UserGroup>("GroupID"11"UserID = @UserID and GroupID = @GroupID"int.Parse(listUsers.SelectedValue), int.Parse(listGroups.SelectedValue));
     74
     75        DbTransaction tran = Facade.BeginTransaction();
     76
     77        try
     78        {
     79            if (userGroups != null && userGroups.Length > 0)
     80            {
     81                Facade.Delete<Entity.UserGroup>("UserID = @UserID and GroupID = @GroupID", userGroups[0].UserID, userGroups[0].GroupID, tran);
     82            }

     83
     84            Entity.UserGroup newUserGroup = Facade.Create<Entity.UserGroup>();
     85            newUserGroup.UserID = int.Parse(listUsers.SelectedValue);
     86            newUserGroup.GroupID = int.Parse(listGroups.SelectedValue);
     87            Facade.Insert<Entity.UserGroup>(newUserGroup, tran);
     88
     89            newUserGroup.GroupID = int.Parse(listSubGroups.SelectedValue);
     90            Facade.Insert<Entity.UserGroup>(newUserGroup, tran);
     91
     92            tran.Commit();
     93
     94            btnViewUsersInGroup_Click(nullnull);
     95        }

     96        catch
     97        {
     98            tran.Rollback();
     99            throw;
    100        }

    101        finally
    102        {
    103            Facade.CloseTransaction(tran);
    104        }

    105    }

    106
    107    protected void listGroups_SelectedIndexChanged(object sender, EventArgs e)
    108    {
    109        RefreshSubGroups();
    110    }

    111}

    这里都是非常简单的查询和绑定代码,具体的效果大家可以直接运行示例来看。在这里您只需关注前述视图的使用,可以看到,如此进行正反查询时非常便利的,而当插入新数据时,当然是直接操作UserGroup表,也很容易。

    总结

    让我们来总结一下该方案相对传统ORM方案的主要优缺点。

    优点:本方案无需配置,引用程序集就能使用,上手容易,起点低,使用灵活,能够快速应对需求变化,强类型不易出错,还有一点很重要,需要用户写的代码极大减少;

    缺点:需要建较多视图,数据底层对使用者不够透明。

    欢迎大家评判、指教!


  • 相关阅读:
    初步认识数据库系统
    相对路径与绝对路径
    数据库系统的结构抽象与演变
    unity物体穿过地面
    Matlab imadjust详解(转载)
    div水平垂直居中及块内元素居中
    Java中HashMap的使用
    Java中HashSet的使用
    Java中数组的使用
    数据结构_堆
  • 原文地址:https://www.cnblogs.com/teddyma/p/366350.html
Copyright © 2020-2023  润新知