在我这个系列中,我主要以我正在开发的云会员管理系统为例进行介绍Web API的应用,由于云会员的数据设计是支持多个商家公司,而每个公司又可以包含多个店铺的,因此一些字典型的数据需要考虑这方面的不同。如对于证件类型,收费处理状态,民族,职称等这些固定化的内容,我们可以放到全局字典里面,但是对于一些如会员相关的字典数据,如产品单位、产品类型等内容,如果也全部规定为全局的系统字典,那么就缺乏灵活性,这些数据应该可以由各自进行差异化处理。

1、云会员系统的字典数据模型

我们先来了解下基于Web API接口的云会员管理系统的总体界面效果。

由于一般的云会员系统,都是允许用户注册一个公司,然后公司层面开设多个商铺的,如系统的登陆界面如下所示。

因此数据的范围需要考虑的更广,他们的关系如下所示。

而我们原先设计的字典模型如下所示。

而在公司数据这个层次上,我们需要考虑公司层级的数据字典存储,但是我们进一步分析可以看到,虽然数据字典数据是公司层级的,但是数据字典的类型(如证件类型、产品类型等)这些是固定不变的,也就是我们如果存储公司层级的字典数据,那么也只是需要存储对应的字典项目即可。因此我们可以增加多一个和TB_DictData的数据表类似的表进行存储即可,它的数据设计如下所示。

为了方便在系统里面使用同一的字典项目内容,我们创建一了一个统一的字典项目管理模块,也就是系统字典管理界面,如下所示。

2、公司层级的字典数据存储实现

有了上面的设计模型,相信大多数人员都可以想到它的具体实现思路了。

首先我们需要以系统字典数据为参考,如默认就是取系统的字典项目数据,如果公司级别的用户修改或者删除了字典数据内容,那么对应的字典类别的字典项目就应该以修改的为准了。

但是我们不可能为新建公司账户的时候,都为每个公司自动创建一份对应类型的字典数据,那样稍显麻烦,而且一开始就创建也比较麻烦。

先建立一个公司字典的数据管理界面,它和字典数据管理界面一样,不过是存储在另外一个表里面,自动根据当前用户的公司标识进行存储的。

批量添加公司字典的数据如下所示。

一般我们在使用公司层级的字典数据或者系统公共层级的字典数据的时候,都是根据字典类型进行判断的。

因此在公司层级根据字典项目类型获取数据的时候,我们在业务接口底层做了判断,判断如果对应公司的字典项没有数据,则复制一份过去,如果公司层次有对应的数据类型,那么就获取公司层级的字典项目数据即可。

具体的代码逻辑如下所示。

        /// <summary>
/// 根据字典类型名称获取所有该类型的字典列表集合
/// </summary>
/// <param name="dictType">字典类型名称</param>
/// <param name="corpId">公司ID</param>
/// <returns></returns>
public List<CorpDictDataInfo> FindByDictType(string dictTypeName, string corpId)
{
ICorpDictData dal = baseDal as ICorpDictData;
List<CorpDictDataInfo> list = dal.FindByDictType(dictTypeName, corpId); //如果公司字典没有数据,则从系统字典获取
if (list.Count == )
{
List<DictDataInfo> dict = BLLFactory<DictData>.Instance.FindByDictType(dictTypeName);
foreach (DictDataInfo info in dict)
{
list.Add(new CorpDictDataInfo(info, corpId));
} //写入公司字典表,避免下次再去获取
foreach (CorpDictDataInfo info in list)
{
baseDal.Insert(info);
}
}
return list;
}

在Web API的控制器接口,还是和其他的处理一样,增加对应的参数处理即可。

        /// <summary>
/// 根据字典类型名称获取所有该类型的字典列表集合
/// </summary>
/// <param name="dictType">字典类型名称</param>
/// <param name="corpId">公司ID</param>
/// <returns></returns>
[HttpGet]
public List<CorpDictDataInfo> FindByDictType(string dictTypeName, string corpId, string token)
{
//令牌检查,不通过则抛出异常
CheckResult checkResult = CheckToken(token); return BLLFactory<CorpDictData>.Instance.FindByDictType(dictTypeName, corpId);
}

在Facade层定义字典的对应接口的时候,我们的代码如下所示

        /// <summary>
/// 根据字典类型名称获取所有该类型的字典列表集合
/// </summary>
/// <param name="dictType">字典类型名称</param>
/// <param name="corpId">公司ID</param>
/// <returns></returns>
[OperationContract]
List<CorpDictDataInfo> FindByDictType(string dictTypeName, string corpId);

在基于Web API的封装调用接口,我们的调用封装类如下所示。其中token以及Web API的相关参数处理,在基类模块进行了封装,减少了很多代码的拼接。

     /// </summary>
/// <param name="dictType">字典类型名称</param>
/// <param name="corpId">公司ID</param>
/// <returns></returns>
public List<CorpDictDataInfo> FindByDictType(string dictTypeName, string corpId)
{
var action = "FindByDictType";
string url = GetTokenUrl(action) + string.Format("&dictTypeName={0}&corpId={1}", dictTypeName, corpId); List<CorpDictDataInfo> result = JsonHelper<List<CorpDictDataInfo>>.ConvertJson(url);
return result;
}

然后我们在界面上的字典项目下拉列表,则可以通过扩展函数的方式进行绑定。

        /// <summary>
/// 初始化字典列表内容
/// </summary>
private void InitDictItem()
{
//初始化代码
this.txtProductType.BindDictItemsByCorp("会员产品类型", LoginUserInfo.CompanyId);
}
        /// <summary>
/// 绑定下拉列表控件为指定的数据字典列表[如果公司字典记录不存在,则使用系统字典记录,否则使用公司记录]
/// </summary>
/// <param name="combo">下拉列表控件</param>
/// <param name="dictTypeName">数据字典类型名称</param>
public static void BindDictItemsByCorp(this ComboBoxEdit combo, string dictTypeName, string corpId)
{
BindDictItemsByCorp(combo, dictTypeName, corpId, null);
} /// <summary>
/// 绑定下拉列表控件为指定的数据字典列表[如果公司字典记录不存在,则使用系统字典记录,否则使用公司记录]
/// </summary>
/// <param name="combo">下拉列表控件</param>
/// <param name="dictTypeName">数据字典类型名称</param>
/// <param name="defaultValue">控件默认值</param>
public static void BindDictItemsByCorp(this ComboBoxEdit combo, string dictTypeName, string corpId, string defaultValue)
{
Dictionary<string, string> dict = CallerFactory<ICorpDictDataService>.Instance.GetDictByDictType(dictTypeName, corpId);
List<CListItem> itemList = new List<CListItem>();
foreach (string key in dict.Keys)
{
itemList.Add(new CListItem(key, dict[key]));
} BindDictItems(combo, itemList, defaultValue);
}

以上就是一个整体性的思路,并在系统中能够顺利解决问题的做法,希望大家可以借鉴。

系列文章如下所示:

Web API应用架构在Winform混合框架中的应用(1)

Web API应用架构在Winform混合框架中的应用(2)--自定义异常结果的处理

Web API接口设计经验总结

Web API应用架构在Winform混合框架中的应用(3)--Winfrom界面调用WebAPI的过程分解

Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用

Web API应用架构在Winform混合框架中的应用(5)--系统级别字典和公司级别字典并存的处理方式

Web API应用架构在Winform混合框架中的应用(5)--系统级别字典和公司级别字典并存的处理方式的更多相关文章

  1. Web API应用架构在Winform混合框架中的应用(4)--利用代码生成工具快速开发整套应用

    前面几篇介绍了Web API的基础信息,以及如何基于混合框架的方式在WInform界面里面整合了Web API的接入方式,虽然我们看似调用过程比较复杂,但是基于整个框架的支持和考虑,我们提供了代码生成 ...

  2. Web API应用架构在Winform混合框架中的应用(3)--Winfrom界面调用WebAPI的过程分解

    最近一直在整合WebAPI.Winform界面.手机短信.微信公众号.企业号等功能,希望把它构建成一个大的应用平台,把我所有的产品线完美连接起来,同时也在探索.攻克更多的技术问题,并抽空写写博客,把相 ...

  3. Web API应用架构在Winform混合框架中的应用(2)--自定义异常结果的处理

    在上篇随笔<Web API应用架构在Winform混合框架中的应用(1)>中我介绍了关于如何在Winfrom里面整合WebAPI,作为一个新型数据源的接入方式,从而形成了三种不同的数据提供 ...

  4. Web API应用架构在Winform混合框架中的应用(1)

    在<Web API应用架构设计分析(1)>和<Web API应用架构设计分析(2)>中对WebAPI的架构进行了一定的剖析,在当今移动优先的口号下,传统平台都纷纷开发了属于自己 ...

  5. Web API应用架构设计分析(1)

    Web API 是一种应用接口框架,它能够构建HTTP服务以支撑更广泛的客户端(包括浏览器,手机和平板电脑等移动设备)的框架, ASP.NET Web API 是一种用于在 .NET Framewor ...

  6. Web API应用架构设计分析(2)

    在上篇随笔<Web API应用架构设计分析(1)>,我对Web API的各种应用架构进行了概括性的分析和设计,Web API 是一种应用接口框架,它能够构建HTTP服务以支撑更广泛的客户端 ...

  7. 在Winform混合式框架中整合外部API接口的调用

    在我们常规的业务处理中,一般内部处理的接口多数都是以数据库相关的,基于混合式开发的Winform开发框架,虽然在客户端调用的时候,一般选择也是基于Web API的调用,不过后端我们可能不仅仅是针对我们 ...

  8. [angularjs] MVC + Web API + AngularJs 搭建简单的 CURD 框架

    MVC + Web API + AngularJs 搭建简单的 CURD 框架 GitHub 地址:https://github.com/liqingwen2015/Wen.MvcSinglePage ...

  9. ABP开发框架前后端开发系列---(5)Web API调用类在Winform项目中的使用

    在前面几篇随笔介绍了我对ABP框架的改造,包括对ABP总体的介绍,以及对各个业务分层的简化,Web API 客户端封装层的设计,使得我们基于ABP框架的整体方案越来越清晰化, 也越来越接近实际的项目开 ...

随机推荐

  1. 【原创】三分钟教你学会MVC框架——基于java web开发(2)

    没想到我的上一篇博客有这么多人看,还有几位看完之后给我留言加油,不胜感激,备受鼓励,啥都别说了,继续系列文章之第二篇.(如果没看过我第一篇博客的朋友,可以到我的主页上先浏览完再看这篇文章,以免上下文对 ...

  2. Web语义化

    在昨天和做SEO的同学聊了一会儿,当然我没有学会搜索引擎优化的技巧和知识,但在此之前一直对HTML5中header.footer.sidebar.article等标签嗤之以鼻,觉得这个和div没有什么 ...

  3. 每天一个linux命令(54):ping命令

    Linux系统的ping命令是常用的网络命令,它通常用来测试与目标主机的连通性,我们经常会说“ping一下某机器,看是不是开着”.不能打开网页时会说“你先ping网关地址192.168.1.1试试”. ...

  4. EF架构~豁出去了,为了IOC,为了扩展,改变以前的IRepository接口

    回到目录 使用了4年的IRepository数据仓储接口,今天要改变了,对于这个数据仓储操作接口,它提倡的是简洁,单纯,就是对数据上下文的操作,而直正的数据上下文本身我们却把它忽略了,在我的IRepo ...

  5. EF架构~CodeFirst模型下的数据初始化

    回到目录 我为什么会来 在传统的大型系统设计中,数据库建模是个比开发更早的环节,先有数据库,然后是ORM模型,最后才是开发程序,而这种模型在EF出现后发生了转变,而且有可能将来会被code first ...

  6. Atitit。木马病毒原理机密与概论以及防御

    Atitit.木马病毒原理机密与概论以及防御 1. 定时截屏木马1 1.1. QQ聊天与微信聊天木马1 2. 文档木马1 3. 病毒木马的触发方式2 4. 远程木马2 5. 漏洞木马2 6. 病毒木马 ...

  7. EasyUI Datagrid Datetime(EasyUI DataGrid 时间格式化)

    EasyUI DataGrid 时间格式化 方法一: var Common = { //EasyUI用DataGrid用日期格式化 TimeFormatter: function (value, re ...

  8. Mybatis中SqlMapper配置的扩展与应用(2)

    三.子表删除兼容问题 这个问题,使用SQL配置函数不太好处理,而且就算使用SQL配置函数,也不够直观,有点自动生成SQL的意味,太Hibernate了(不过要是可以兼收Hibernate和Mybati ...

  9. java容器详细解析

    前言:在java开发中我们肯定会大量的使用集合,在这里我将总结常见的集合类,每个集合类的优点和缺点,以便我们能更好的使用集合.下面我用一幅图来表示 其中淡绿色的表示接口,红色的表示我们经常使用的类. ...

  10. png图片制作任意颜色的小图标

    本内容只要是对张鑫旭PNG格式小图标的CSS任意颜色赋色技术的这篇文章进行详细说明. HTML: <i class="icon"><i class="i ...