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方案的主要优缺点。

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

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

欢迎大家评判、指教!


posted @ 2006-04-04 10:51  Teddy's Knowledge Base  Views(3631)  Comments(9Edit  收藏