分享一个进销存项目(多层架构)

花了点时间完成了一个进销存的项目,个人觉得对逻辑分析,架构思想都有一定的体会,故拿出来和大家分享下,首先介绍下项目的功能吧,主要功能有采购管理,销售管理,库存管理,人员信息管理,系统管理等,不过写这篇博客的主要目的并不是讲解如何实现项目功能,而是分享下该项目的架构思想、实现步骤和碰到的一些问题,分享下心得体会罢了......

数据库设计

下面进入主题,首先贴上项目的主界面,由于对界面要求不是很高,所以界面相对来说比较简单,甚至可是说是简陋了,,呵呵,不过重点不在界面上,勇敢的直接上图:

架构:

首先说说项目架构吧,,贴上项目模块图:

从图中可知,项目总共分10个模块,采用三层架构+WCF+反射+抽象工厂来搭建,其中还加入了单例模式,缓存机制。下面分别说说每个模块的作用:

Insigma.PSI.UI:WinForm界面层

Insigma.PSI.Model:模型层,数据实体

Insigma.PSI.IBLLService:业务逻辑接口层,是定义逻辑层的契约层

Insigma.PSI.BLLService:业务逻辑实现层,是对接口的实现

Insigma.PSI.IDAL:数据访问接口层,是定义访问层的契约层

Insigma.PSI.SqlServerDAL:数据访问实现层,实现访问接口层,主要是针对SQL数据库

Insigma.PSI.OracleDAL:数据访问实现层,实现访问接口层,主要是针对Oracle数据库

Insigma.PSI.Utility:工具层,主要存放了Oracle数据库,SQL数据库的数据库操作类

Insigma.PSI.DBFactory:抽象工厂层,主要为考虑可以使项目可以适用Oracle数据库和SQL数据库,就搭建了一个抽象工厂层,分别在Oracle数据库层和SQL数据库层建立一个 工 厂来实现该抽象工厂

C:\..\WcfWebRelease\:web层,主要用来发布WCF服务

项目:

简单的分析完了框架的每个模块的作用,然后讲讲项目,由于篇幅问题,无法讲解项目的所有功能,所以在这里就拿出一个模块来讲解下,我选择了库存模块

从图中可知,库存模块主要实现四个模块的功能,即库存列表、出库/入库、库存明细、库存警报

首先看看库存列表,上图:

库存列表的功能比较简单,只是实现了仓库的增、删、改、查,由于功能比较简单,也就不多做讲解了....

再贴上出库/入库模块图:

这块应该算是库存模块中的核心模块了,因为该块的业务逻辑比较多,比较繁琐,大致讲讲业务逻辑吧,大致的逻辑为:出库单/出库单-->填写订单-->出库/入库-->修改库存信息,按照这个顺序来完成入库出库,顺序不能颠倒,同时还要实现订单的删除,修改,在修改库存信息时由于表和表之间有很多的外键关系,所以要同时删除多张表中含有删除信息的内容,实现联级删除,由于这里考虑到要保证结果的一致性,所以用事务来实现。再看看界面,为了保证用户按照这个逻辑顺序操作,首先我添加了一对单选框(出库单,入库单),当单选框都没有选中时,保存订单按钮、出库、入库按钮都是不可用状态,当用户选择了订单类型之后,保存订单按钮转为可用状态,需要用户填写订单信息,填写好对应信息之后保存订单,保存成功之后列表框中出现刚生产的订单,同时订单号是自动来生成的,入库单是“S_I”开头,出库单是"S_O"开头,后面五位数字为随机生成,这样生成的订单号易于区别,也避免了订单号的重复,然后根据用户选择的订单类型,对应的按钮转为可用(出库单-->出库按钮) ,这样就保证了用户始终是按照这个顺序来操作,同时订单列表框下有删除订单按钮,点击可以删除选中按钮。

下面那出库为例,看看如何实现入库:

点击【入库】按钮,弹出商品选择窗口,窗口中显示了订单号和仓库编号,同时还有一个【选择】按钮,通过该按钮选择商品

点击【选择】按钮,弹出商品列表窗口,由于我这里商品记录比较少,只有两条,我们就选第二条吧,点击【确定】按钮

这时的"入库信息"窗口中就填写上了刚才选择商品的信息,然后只要在填写上入库数量,点击【确定】就完成了入库操作了,如图:

出库的思路和入库一样,也是先选择出库单,然后填写出库单信息并保存订单,然后再给订单上添加商品,过程也是通过选择实现,由于类同,就不赘述了...

然后是库存明细模块,上图:

该模块主要实现的功能是对存放在各个仓库中的商品进行清点,点击商品的行头就显示出该商品的信息:编号、数量、盘点日期、存放仓库;填写好盘点的数量之后单击【保存】按钮,实现保存盘点数据,这个模块也没什么难点,唯一复杂点的就是因为同样的货品可以存放到不同的仓库中,所以点击时要搜索出该商品所在的所有仓库编号,并在“存放仓库”列表中显示。

最后是库存警报模块,上图:

该模块主要来设置库存上限和库存下限,实现当库存中存放的商品的数量超过库存上限或者低于库存下限时,弹出警告框提醒。

这样,我们就简单的把项目的功能叙述了下,当然还有一些细节的功能,这里就不再罗列了.....

代码:

由于代码端模块较多,我们就按照程序执行调用的层次关系来罗列.这样相对来说看起来思路比较清晰......Model层只是定义了需要用到的实体而已,不再赘述了.....

1>.Insigma.PSI.IBLLService层

可以看到有很多的功能类,无法全部讲解,所以就挑选一块,后面的模块层中也着重讲解挑选的这一块,我挑选了库存管理模块,即IStoreManageBLLService,贴上该类的代码:

IStoreManageBLLService

由于我们要用到WCF来发布服务,所以这里的每个方法都添加了WCF特性,主要功能是获取仓库、获取仓库编号、对仓库的增、删、改、查;由于出库入库对商品的数量有影响,又由于不存在同一张表格中,所以我们专门定义了一个方法来实现修改商品数量;然后出库入库对应一张库存明细表,执行操作之后要修改该表,记录信息,同时也可以获取该表信息,定义的方法就那么多了.....

2>Insigma.PSI.BLLService层

这层是对上面提及的接口层的实现,但除了实现之外,我还在这里加了一个反射机制,在这层按照原来三层的思路是要调用DAL层来实现对数据库的操作,但因为考虑到要适用于不同的数据库,所以我们不知道要调用哪个数据库层的DAL来操作,这就是这个反射存在的意义了,我们可以通过反射来读取配置文件中定义的数据库信息,从而创建对应数据库类的实例来操作....先贴上StoreManageBLLService的代码,之后再接着讲解,看到了代码思路会清晰点:

StoreManageBLLService

从代码中可以看到我们是通过反射来获取DAL的实例的,然后再调用该实例的方法,那么反射里是怎么实现的呢?贴上代码:

反射

从代码可知,我们获取了配置文件中定义的程序集以及数据库类的信息,通过加载该程序集来获取该数据库类的实例,同时,添加了单例模式,因为考虑到每次加载该类库的时候都要来获取一次数据库类的实例,但是该数据库类只要配置文件定义不变他就不会变,所以不用每次都去创建实例 ,只需要创建一次就可以了,提高性能,所以就是单例模式的作用了,这里首先定义了一个AbstractFactory类型(后面会讲到)变量来接受创建好的实例,该变量也是static类型的,保证唯一性,我这里是将构造函数改为static的方式,然后在静态构造函数中实例化数据库类,并赋值给定义好的变量,因为静态构造函数只会执行一次,之后就不会执行了,这就保证了只实例一次,然后定义一个GetFactory()方法来返回数据库实例,这样就达到了"单例"的效果了,当然单例模式还有一种思路是将构造函数设为private,也同样定义一个静态变量和静态方法来创建实例,同样保证了"单例"。

然后看看配置文件中定义的数据库信息:

web.config

可以看到配置文件中定义了程序集的名称,数据库类的名称,但其实这个数据库类就是工厂类的名称。反射中提到了AbstractFactory类型,这是抽象工厂模块中的内容,那么为什么要有这个抽象工厂呢??存在的意义是什么呢?我们就来看看抽象工厂,我的思路:定义一个抽象工厂,里面是一些抽象产品,对应于IDAL中定义的类型的产品,然后在每个数据库类库中定义一个具体工厂,该具体工厂继承抽象工厂,重写抽象产品,返回具体产品,即对IDAL接口类的实现类(DAL)的对应实例,那你会想到了,如没有工厂我们照样可以实现用反射类获取实例的呀,但你想想这时候获取到得实例是什么?它就是我们工厂类中的单个产品而已,当我们的产品有很多的时候怎么办呢,一个DAL类库中的每个类都是一个产品,那难道我们把每个产品都在配置文件中去定义,然后用到的时候通过反射去获取么??显然不可能,所以我们加了抽象工厂模式了,在DAL类库中有一个具体的工厂类,我们所有的产品都由该工厂来创建,那我们获取的是时候只需要获取工厂实例,然后通过该实例来创建我们需要的产品就可以了......

3>Insigma.PSI.IDAL层

同样的拿IStoreManageDAL类讲解,上代码:

IStoreManageDAL

这也是一个接口类,接口的作用就是规范行为,定义一种契约,继承该接口的类都必须实现契约,所以这里主要来约束DAL实现层的行为

4>.Insigma.PSI.DBFactory

抽象工厂模块中就一个抽象工厂类,就直接贴上类代码:

AbstractFactory

在抽象类中为每个在IDAL中定义的类型都对应的建立了一个属性(也可以定义成方法),因为加了抽象工厂之后,IDAL中的每个类都是一个抽象产品类,是产品类的基类,而DAL中的每个类都是该基类的派生类,都实现了基类中定义的方法,最终返回的具体产品的类型都为抽象产品类型(子类赋值给基类)。

5>.Insigma.PSI.OracleDAL

有一个工厂类,用于创建具体产品实例,贴上工厂类代码:

Oracle工厂

在创建具体产品实例的时候我们还用到了缓存机制,每次使用产品功能的时候都回去实例化一个具体的产品返回,所以多次使用同一产品的时候就做了很多无谓的实例化,所以我加了一层缓存,用来将产品的实例缓存起来,下次再需要该产品时直接从缓存中读取就可以了,提高了性能。

我这里用的是Runtime.Cache.Get()来获取存,Runtime.Cache.Insert()来添加缓存。

当然还有一种方法是用HttpContext.Current.Cache.Get()来取,HttpContext.Current.Cache.Insert()来添加缓存。

至于这两者的区别,要涉及到asp.net生命周期和其他方面的一些内容了,这里就不解析了.....

SqlDAL中的内容和Oracle类似,也是建立了一个工厂创建具体产品,同样继承并实现了IDAL中定义的方法,这里也不罗列了......

到这里抽象工厂的角色都出现了,那么来总结下:

抽象工厂:AbstractFactory类

抽象产品:IDAL类库中每个类

具体工厂:1.OracleFactory  2.SqlFactory

具体产品:DAL层中定义的每个类

6>.WCF

我们仍然拿StoreManageBLL.svc来讲解,贴上代码:

StoreManageBLLService

定义了程序集的名称和服务类名,然后在web.config中配置服信息,上代码:

web.config

7>.Insigma.PSI.UI

服务配置好了,那我们客户端怎么调用呢??所以我们需要在客户端的app.config配置文件中添加终结点信息,上代码:

app.config

同时,我在客户端专门定义了一个类用来创建wcf代理,返回BLL实例,上代码:

代理类

Utility层没什么好讲的,就是两个数据库操作类,一个Oracle类,一个SQL类,这里就不贴图贴代码了....

疑问解答

架构、项目、代码端都讲解完成了....接下来和大家分享项目中碰到的一个绑定的问题....

首先贴上要绑定的Model层信息:

外键对象

讲讲要求吧,就是希望当页面载入是显示订单表_商品详细表的综合信息,由于是不同的表,所以我在Model层建立了一个单独的Model类,里面是一对外键对象,因为存在主外键的关系,所以我就考虑到了用外键对象来存放数据,然后通过外键建立两张表的视图,然后获取视图数据,OK,获取完全没有问题,获取到了就是页面端的绑定了,按照原来的思路,上代码:

错误绑定

结果就是,始终绑不上,经过深思熟虑之后,才觉得应该是外界对象的问题,所以收集资料,终于发现错误点确实在外键对象上,外键对象无法直接直接绑定上去,至少DataGridView无法直接绑定,web中的Eval()、Bind()可以绑定外键对象(经测试)........好了,问题找到了就要开始解决了,最后终于发现了一种手动绑定的方法,上代码:

正确绑定

至此,,本篇博客就算告一个段落了,欢迎大家评点指导。。。。。。。

分类: 架构思想

好文要顶 关注我 收藏该文

HolyKnight
关注 - 8
粉丝 - 167

+加关注

27

0

« 上一篇: 委托与事件
» 下一篇: 邮件发送(附源码)

posted @ 2012-08-31 09:41  HolyKnight  阅读(17580)  评论(198)  编辑  收藏  举报

< Prev 1 2 3 4

评论

回复 引用

#151楼 
2012-09-01 13:26 | 桦仔外键应该是这样:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

using System;

using System.Collections.Generic;

namespace Maticsoft.Model

{

    /// <summary>

    /// 实体类Accounts_Roles 。(属性说明自动提取数据库字段的描述信息)

        /// 根据RoleID这个字段

    /// </summary>

    [Serializable]

    public class Accounts_Roles

    {

        public Accounts_Roles()

        {}

        #region Model

        private int _roleid;

        private string _description;

        /// <summary>

        ///

        /// </summary>

        public int RoleID

        {

            set{ _roleid=value;}

            get{return _roleid;}

        }

        /// <summary>

        ///

        /// </summary>

        public string Description

        {

            set{ _description=value;}

            get{return _description;}

        }

        #endregion Model

        private List<Accounts_UserRoles> _accounts_userroless;

        /// <summary>

        /// 子类

        /// </summary>

        public List<Accounts_UserRoles> Accounts_UserRoless

        {

            set{ _accounts_userroless=value;}

            get{return _accounts_userroless;}

        }

    }

    /// <summary>

    /// 实体类Accounts_UserRoles 。(属性说明自动提取数据库字段的描述信息)

    /// </summary>

    [Serializable]

    public class Accounts_UserRoles

    {

        public Accounts_UserRoles()

        {}

        #region Model

        private int _userid;

        private int _roleid;

        /// <summary>

        ///

        /// </summary>

        public int UserID

        {

            set{ _userid=value;}

            get{return _userid;}

        }

        /// <summary>

        ///

        /// </summary>

        public int RoleID

        {

            set{ _roleid=value;}

            get{return _roleid;}

        }

        #endregion Model

    }

}

分享一个进销存项目(多层架构)相关推荐

  1. 开源依旧:再次分享一个进销存系统

    开篇 我之前发过一篇博文<两天完成一个小型工程报价系统(三层架构)>,不少朋友向我要源码学习,后来久而久之忘记回复了.今天我再分享一个进销存系统,只为学习,没有复杂的框架和设计模式,有的是 ...

  2. Java-私塾图书进销存项目视频--(趣盘下载)

    Java-私塾图书进销存项目视频地址: http://wuguo623778063.qupan.com/?folder=1273452

  3. 用Python开发了一个进销存管理的小软件

    研究生毕业之后,就进入国企工作,工作内容偏产品和售前,几乎没写过代码了,有个朋友是开游泳馆的,也会有少量商品的售卖,问我能不能给她开发一个小软件,记录商品的入库出库,统计下金额,恰好工作中今年也用到了 ...

  4. 1.用Python写了一个进销存管理的软件~需求分析界面设计数据库设计技术路线选择~

    一.需求分析 总体来说,就是一个在游泳馆使用的进销存管理软件,记录商品的入库.出库情况,以及统计销售的金额等~ 整个系统有三类用户,系统管理员.公司管理员和公司销售员,系统管理员负责录入公司信息以及分 ...

  5. 开发一个进销存系统大概的时间及成本约是多少?

    不同的企业进销存管理千差万别.个性化程度高,市场上的产品无法覆盖各个行业的管理需求. 那就给题主提供一个可根据自身需求自定义搭建的进销存系统,可以参考下: 下面这个进销存系统包含数据看板.基础数据.采 ...

  6. 只需三步,教你搭建一个进销存管理系统!

    如果你常常面临:进销存软件功能不全.功能冗余.价格昂贵,性价比不高的情况-- 可以考虑使用[零代码搭建]了! 在简道云可以根据自身需求快速搭建出进销存管理系统.相比较其他标准进销存软件,用简道云搭建进 ...

  7. Java swing项目【超市管理系统】(进销存项目)

    不知道大家最开始学习Java的时候有没有做过这个项目,这次给大家分享一个之前做过的java  swing项目. 工具: eclipse MySQL数据库 使用技术: JDBC java swing M ...

  8. 编程小白一个月开发一套WEB进销存系统

    一个完全不懂编程的人在一个月内开发出一套WEB进销存系统,这听上去感觉有点不可思议,但这的确是事实.当然,如果靠去学会编程语言然后动手开发,这么短时间完成项目是不可能了,所以运用好工具才是关键. 进销 ...

  9. 珠宝管理系统java,基于jsp的珠宝首饰进销存管理系统-JavaEE实现珠宝首饰进销存管理系统 - java项目源码...

    基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的珠宝首饰进销存管理系统, 该项目可用各类java课程设计大作业中, 珠宝首饰进销存管理系统的系统架构分为前后台两部 ...

最新文章

  1. 如何找出数组中第二大的数
  2. 从零开始学ios开发(十):Multiview Applications(多个xib之前的切换)
  3. SpringCloud:Zuul 路由访问(基本使用、路由功能、过滤访问、服务降级)
  4. Python包和__init__.py文件
  5. win10切换桌面_探秘Win10系统中的不可错过的实用功能
  6. 大数据基础概念思维导图
  7. 【Java】我的世界Java版外挂制作 [0] - 配置环境
  8. 【设计开发命名必备】英语单词缩写规则
  9. 短视频三要素之封面,如何设计引人关注的封面呢?
  10. 单商户商城系统功能拆解39—分销应用—分销等级
  11. Python全套视频
  12. 【Arduino】重生之Arduino 学僧(1)----Arduino简介
  13. iPhone手机 开发者模式 解读
  14. 计算机毕业设计Java“臻宝”书画竞拍系统(源码+系统+mysql数据库+lw文档)
  15. 糕头:二维火小程序初探
  16. Excel的统计函数(1)
  17. css 视频播放列表,jquery结合CSS实现的多样式多视频列表连播效果源码
  18. 老司机带你秒懂结构体
  19. 最短路径问题-Floyed算法
  20. 2022-9-19周报

热门文章

  1. 备战NOI 数据结构——栈与单调栈(stack) 以及后缀表达式
  2. 【调剂】山东师范大学信息科学与工程学院2023年招收硕士研究生预调剂公告
  3. 二级路由器的设置(品牌:小米和TPLINK)
  4. 极验滑块加密JS分析(一)
  5. hive 中的location
  6. CTFSHOW 新生杯web
  7. java swing 控件_Java Swing组件
  8. Android Loading加载动画
  9. iapp退出软件按钮代码_还在为金蝶财务软件发愁吗?超详细!金蝶财务软件实操流程,速收!...
  10. 以太网(局域网)交换机工作原理