文档章节

两天完成一个小型工程报价系统(三层架构)

 木宛城主
发布于 2015/03/02 19:38
字数 1480
阅读 8
收藏 1
点赞 0
评论 0

花了两天,整理了一下三层架构,顺便练了一个小型三层架构——工程报价系统。

功能很简单,完成基本的增删改查

  • 搭建项目三层结构

  • 界面的设计以及美化

  • 分层代码的设计与实现

  1. 模型层:由于表设计时存在主外键关系,故把表映射成对象时添加一个外键对象来保存外键那张表的相关数据。

 

// 外键实体
            private Product _product;
            private Project _project;

            public Project _Project
            {
                get { return _project; }
                set { _project = value; }
            }

            public Product _Product
            {
                get { return _product; }
                set { _product = value; }
            }

 

  2.数据访问层:把数据封装成Model对象的各层之间传递

  我个人不喜欢三层之间传递DataSet数据集,我的理解是尽量不在BLL层出现DataSet,所以我在DAL层把所有获取的数据封装成IEnumerable集合,然后返回。

protected IEnumerable<ProjectItem> ToModelsByFK(SqlDataReader reader)
         {
             var list = new List<ProjectItem>();
             while (reader.Read())
             {
                 list.Add(ToModelByFK(reader));
             }
             return list;
         }  

      
public ProjectItem ToModelByFK(SqlDataReader reader)
         {
             ProjectItem projectItem = new ProjectItem();
             projectItem._Product = new Product();
             projectItem._Project = new Project();
             projectItem.ID = (int)ToModelValue(reader, "ID");
             projectItem._Product.ID = (int)ToModelValue(reader, "ProductID");
             projectItem._Project.ID = (int)ToModelValue(reader,"projectID");
             projectItem._Product.Manufacturer = ToModelValue(reader, "Manufacturer").ToString();
             projectItem._Product.Parameters = ToModelValue(reader, "Parameters").ToString();
             projectItem._Product.Price = decimal.Parse( ToModelValue(reader, "Price").ToString());
             projectItem._Product.ProductName = ToModelValue(reader, "ProductName").ToString();
             projectItem._Product.Specification = ToModelValue(reader, "Specification").ToString();
             projectItem._Product.Unit = ToModelValue(reader, "Unit").ToString();
             projectItem.Count = (int)ToModelValue(reader, "Count");
             projectItem.TotalMoney = (decimal)ToModelValue(reader, "TotalMoney");
             projectItem.UnitPrice = (decimal)ToModelValue(reader, "UnitPrice"); 
             return projectItem;
         }
protected object ToModelValue(SqlDataReader reader,string columnName)
        {
            if(reader.IsDBNull(reader.GetOrdinal(columnName)))
            {
                return null;
            }
            else
            {
                return reader[columnName];
            }
        }

使用GetProjectByCondition方法返回一个封装成对象的 IEnumerable集合

public IEnumerable<Model.Project> GetProjectByCondition(string projectName, string customerName, string contract, string tel)
        {
            StringBuilder sqlWhere = new StringBuilder("select * from Project where 1=1");
            List<SqlParameter> listParameters = new List<SqlParameter>();
            if (!string.IsNullOrWhiteSpace(projectName))
            {
                sqlWhere.AppendLine(" and projectName like @projectName");
                listParameters.Add(new SqlParameter("projectName", "%" + projectName + "%"));
            }
            if (!string.IsNullOrWhiteSpace(contract))
            {
                sqlWhere.AppendLine(" and Contact like @Contact");
                listParameters.Add(new SqlParameter("Contact", "%" + contract + "%"));
            }
            if (!string.IsNullOrWhiteSpace(customerName))
            {
                sqlWhere.AppendLine(" and customer like @customer");
                listParameters.Add(new SqlParameter("customer", "%" + customerName + "%"));
            }
            if (!string.IsNullOrWhiteSpace(tel))
            {
                sqlWhere.AppendLine(" and tel like @tel");
                listParameters.Add(new SqlParameter("tel", "%" + tel + "%"));
            }
            using (SqlDataReader reader = SqlHelper.ExecuteDataReader(sqlWhere.ToString(), listParameters.ToArray()))
            {
                return ToModels(reader);
            }

        }

UpdatePassChecked方法接受一个对象,通过对象的属性来获取数据

public int UpdatePassChecked(ProjectItem projectItem)
         {
             string sql =
                 "UPDATE Project " +
                 "SET " +
             " ProjectName = @ProjectName"
                 + ", Customer = @Customer"
                 + ", Contact = @Contact"
                 + ", Tel = @Tel"
                 + ", DeliveryPlace = @DeliveryPlace"
                 + ", DeliveryTime = @DeliveryTime"
                 + ", TransportCosts = @TransportCosts"
                 + ", PaymentTerm = @PaymentTerm"
                 + ", Bak = @Bak"

             + " WHERE ID = @ID";


             SqlParameter[] para = new SqlParameter[]
            {
                new SqlParameter("@ID", projectItem._Project.ID)
                    ,new SqlParameter("@ProjectName", ToDBValue(projectItem._Project.ProjectName))
                    ,new SqlParameter("@Customer", ToDBValue(projectItem._Project.Customer))
                    ,new SqlParameter("@Contact", ToDBValue(projectItem._Project.Contact))
                    ,new SqlParameter("@Tel", ToDBValue(projectItem._Project.Tel))
                    ,new SqlParameter("@DeliveryPlace", ToDBValue(projectItem._Project.DeliveryPlace))
                    ,new SqlParameter("@DeliveryTime", ToDBValue(projectItem._Project.DeliveryTime))
                    ,new SqlParameter("@TransportCosts", ToDBValue(projectItem._Project.TransportCosts))
                    ,new SqlParameter("@PaymentTerm", ToDBValue(projectItem._Project.PaymentTerm))
                    ,new SqlParameter("@Bak", ToDBValue(projectItem._Project.Bak))
            };

             return SqlHelper.ExecuteNonQuery(sql, para);

         }

Add方法传入一个已经把数据封装好的对象,然后返回一个新的对象(包含新创建生成的ID)

public Product Add(Product product)
        {
                string sql ="INSERT INTO Product (ProductName, Specification, Manufacturer, Parameters, Price, Unit)  output inserted.ID VALUES (@ProductName, @Specification, @Manufacturer, @Parameters, @Price, @Unit)";
                SqlParameter[] para = new SqlParameter[]
                    {
                        new SqlParameter("@ProductName", ToDBValue(product.ProductName)),
                        new SqlParameter("@Specification", ToDBValue(product.Specification)),
                        new SqlParameter("@Manufacturer", ToDBValue(product.Manufacturer)),
                        new SqlParameter("@Parameters", ToDBValue(product.Parameters)),
                        new SqlParameter("@Price", ToDBValue(product.Price)),
                        new SqlParameter("@Unit", ToDBValue(product.Unit)),
                    };
                    
                int newId = (int)SqlHelper.ExecuteScalar(sql, para);
                return GetByID(newId);
        }

 

  3.业务逻辑层:业务逻辑层是项目的核心,业务逻辑上的代码通常在这儿实现(一言难尽)。

简单数据验证:

public bool UpdateThroughChecked(ProjectItem projectItem)
        {
            if (string.IsNullOrEmpty(projectItem._Project.ProjectName))
            {
                throw new Exception("项目名称不能为空");
            }
            //顾客姓名可以为空,但联系人不能为空,所以数据库里就应该设计好
            if (string.IsNullOrEmpty(projectItem._Project.Contact))
            {
                throw new Exception("联系人姓名不能为空");
            }
            if (string.IsNullOrEmpty(projectItem._Project.Tel))
            {
                throw new Exception("联系电话不能为空");
            }
            if (string.IsNullOrEmpty(projectItem._Project.DeliveryPlace))
            {
                throw new Exception("交货地点不能为空");
            }
            if (string.IsNullOrEmpty(projectItem._Project.DeliveryTime))
            {
                throw new Exception("交货时间不能为空");
            }
            if (projectItem._Project.TransportCosts<00)
            {
                throw new Exception("运输费用不能为负数");
            }
            return new DAL.ProjectItemService().UpdatePassChecked(projectItem) > 0;

        }

计算总金额:

public decimal GetProductTotalMoney(int projectID)
        {
            var list = new DAL.ProjectItemService().GetProductTotalMoney(projectID);
            decimal  totalMoney = 0.00M;
            foreach (var model in list)
            {
                totalMoney+=model.TotalMoney.Value;
            }
            return totalMoney;
        }

根据查询条件获取数据集合:

/// <summary>
        /// 根据查询条件获取数据集合
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public IEnumerable<Model.Product> GetProductsByCondition(string condition)
        {
           return new DAL.ProductService().GetProductsByCondition(condition);
       
        }

根据ProjectItemID获取一条记录(封装成对象)

public Model.ProjectItem GetOneProjectItemByID(int ProjectItemID)
        {
            return new DAL.ProjectItemService().GetOneProjectItemByID(ProjectItemID);
        }

增加一条记录:

/// <summary>
        /// 新增一条记录 根据条件
        /// </summary>
        /// <param name="modelProject"></param>
        /// <returns></returns>
        public Model.Project AddPassCheckd(Model.Project modelProject)
        {

            if (string.IsNullOrEmpty(modelProject.ProjectName))
            {
                throw new Exception("项目名称不能为空");
            }
            if (string.IsNullOrEmpty(modelProject.Customer))
            {
                throw new Exception("顾客名称不能为空");
            }
            if (string.IsNullOrEmpty(modelProject.Tel))
            {
                throw new Exception("联系电话不能为空");
            }
            if (modelProject.TransportCosts <= 0)
            {
                throw new Exception("运输费用不能为负数:(");
            }
            return new DAL.ProjectService().Add(modelProject);
           
        }

删除一个项目:

/// <summary>
        /// 删除一个项目
        /// </summary>
        /// <param name="projectID"></param>
        /// <returns></returns>
        public bool DeleteProject(int projectID)
        {
             bool isSucceed=  new BLL.ProjectItemManager().DeleteProjectItemsByProjectID(projectID);
             isSucceed = new DAL.ProjectService().DeleteByID(projectID) > 0 && isSucceed;
             return isSucceed;
        }

4.表现层(UI)

简单的窗体里嵌套窗体:

public void LoadProjectListForm()
        {
            projectListForm = null;
            if (projectListForm==null)
            {
                projectListForm = new ProjectListForm();
            }
            //去掉边框
            projectListForm.FormBorderStyle = FormBorderStyle.None;
            projectListForm.TopLevel = false;//窗体是否是顶级窗体
            projectListForm.Dock = DockStyle.Fill;//填充
            projectListForm.Show();//不写看不到
            panelContainer.Controls.Clear();//清空
            panelContainer.Controls.Add(projectListForm);
        }

绑定数据:

我原先思路是直接在DataGridView里绑定对象的属性,和GridView一样使用,但一直无法绑上去,哪儿错了?

所以只能曲线救国了:

void LoadData()
        {
            var list = new BLL.ProjectItemManager().GetAllProducts(projectID);
            //dataGridViewProjectItems.DataSource = list;//当控件被绑定时无法向其添加Row
            dataGridViewProjectItems.Rows.Clear();
            foreach (var model in list)
            {
                int i = dataGridViewProjectItems.Rows.Add();
                dataGridViewProjectItems.Rows[i].Cells["idColumn"].Value = model.ID;
                dataGridViewProjectItems.Rows[i].Cells["specificationColumn"].Value = model._Product.Specification;
                dataGridViewProjectItems.Rows[i].Cells["productNameColumn"].Value = model._Product.ProductName;
                dataGridViewProjectItems.Rows[i].Cells["manufacturerColumn"].Value = model._Product.Manufacturer;
                dataGridViewProjectItems.Rows[i].Cells["parametersColumn"].Value = model._Product.Parameters;
                dataGridViewProjectItems.Rows[i].Cells["productIDColumn"].Value = model._Product.ID;
                dataGridViewProjectItems.Rows[i].Cells["totalMoneyColumn"].Value = model.TotalMoney;
                dataGridViewProjectItems.Rows[i].Cells["countColumn"].Value = model.Count;
                dataGridViewProjectItems.Rows[i].Cells["unitPriceColumn"].Value = model.UnitPrice;
                dataGridViewProjectItems.Rows[i].Cells["projectIDColumn"].Value = model._Project.ID;
            }

5.项目总结

花了一个周末修修补补完成了这个工程报价系统,算是复习了一把三层架构。

如果有需要这个项目的朋友可以留下邮箱,我发给你,不算很专业,凑合着参考下~~

没想到这么多朋友要我的源码,我很感动。附件我就不传了,我也怕误导新人。有需要的朋友可以留下邮箱,大家一起探讨,我的代码纯当入门阶段,是我个人对三层架构的理解,不足之处,也请多多包涵,提个意见,希望与君互勉。想要更深刻探索我推介《ASP.NET 设计模式》


 源代码下载:

© 著作权归作者所有

共有 人打赏支持
粉丝 2
博文 222
码字总数 199010
作品 0
黄浦
咱们在讨论的时候能不能先确定一个明确的范围呢?最好能把自己的经历简单说一下。

昨天晚上看到了三层,又见三层。别了,三层 有点想法,在这里说一下。和周六活动的讨论没有什么关系,特此声明! 讨论是好的,但是范围不明确的话,就很容易跑题,也容易带出来火药味儿。想这...

金色海洋
2017/12/24
0
0
广告公关公司如何选择项目管理软件

广告公关行业属于大传播行业其中的一种,广告公关公司如果选择管理软件,可以参照传播业管理软件。为什么叫传播业?我们一直在找一个什么样的词把这几个细分行业都囊括进来,发现唯有传播能更...

玄学酱
05/22
0
0
设计讨论:好设计长什么样?

怎样的设计算得上好设计? 就如一百个人眼中有一百个哈姆雷特一样,这个问题多半也不会有标准答案。何况,脱离了具体和细节的业务需求,设计、架构之类的讨论也只剩套路了。 不过,前两天想了...

winters1224
2017/01/03
0
0
不在乎y/RTXCPluginForDelphiSDK

======= #RTXCPluginForDelphiSDK ##Delphi开发RTX插件 (Delphi XE6) 当初开发只是好奇, 所以去研究了下, 花了两天的时间翻译了原C++ SDK到Delphi 目录结构及祥细情况 Demo NotetipsGroup 一...

不在乎y
2014/11/23
0
0
【blade04】用面向对象的方法写javascript坦克大战

前言 javascript与程序的语言比如C#或者java不一样,他并没有“类”的概念,虽然最新的ECMAScript提出了Class的概念,我们却没有怎么用 就单以C#与Java来说,要到真正理解面向对象的程度也是...

范大脚脚
2017/11/16
0
0
【技术专栏】传播业强身三步走:控成本、管创意、提效率

“听了很多道理,不如业者最实际的分享。” 本周起,《商旅专家》于微信公众平台开辟全新【技术专栏】板块。经验丰富的业界大佬将基于自身在行业的所得所感,通过此平台陆续与我们的读者开展...

玄学酱
05/25
0
0
Google SketchUp 7——简单而不简单

自从在VeryCD下了个Google SketchUp 7后,这两天就一直在研究这个。 话说我在3D领域是一个骨灰级菜鸟,3Ds MAX摸了无数次也没入过门,而在SketchUp中却瞬间找到了感觉,很是Happy^^。 看看咱...

老朱教授
2017/11/07
0
0
#最新动态#下周工作计划

昨日完成了【攻克要塞软考高级论文公开课】课程的在线直播,上课讲义已转成PDF上传。 本周末在山东进行系统架构设计师两天面授冲刺培训,课程结束后将开始: 在51CTO发布论文批改服务包。此服...

liuyiok
2015/10/14
0
0
VB源码升级后的几幅截图-VBIDE嵌入窗体、代码资源自动加入

用了整整两天的时间终于完成了功能上的升级,但多国语言版和数据库的加密还不知什么时间能做完,所以一时还不能发布,不过作为“内部人员”倒是可以先用为快:) 一、把原图标进行了修改,可...

刘洪峰iot
2005/08/23
0
0
大型园区网交换设计

大型园区网交换设计 什么是园区网? 园区网顾名思义,指一个园区内的网络(园区一般包含多栋建筑),比如医院,学校,政府单位的网络都可以叫做园区网。后来园区网使用比较广泛,不一定要一个...

永恒2222
2017/04/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

【RocketMQ】Message存储笔记

概述 消息中间件存储分为三种,一是保存在内存中,速度快但会因为系统宕机等因素造成消息丢失;二是保存在内存中,同时定时将消息写入DB中,好处是持久化消息,如何读写DB是MQ的瓶颈;三是内...

SaintTinyBoy
9分钟前
0
0
Android应用Context详解及源码解析

Android应用Context详解及源码解析 本文定位:优质文章收集 本文转载 1 背景 今天突然想起之前在上家公司(做TV与BOX盒子)时有好几个人问过我关于Android的Context到底是啥的问题,所以就马...

lichuangnk
41分钟前
0
0
PostgreSQL的昨天今天和明天

PostgreSQL 是一种非常复杂的对象-关系型数据库管理系统(ORDBMS), 也是目前功能最强大,特性最丰富和最复杂的自由软件数据库系统。有些特性甚至连商业数据库都不具备。 这个起源于伯克利(...

闻术苑
45分钟前
0
0
Mysql对自增主键ID进行重新排序

1,删除原有主键: ALTER TABLE `table_name` DROP `id`; 2,添加新主键字段: ALTER TABLE `table_name` ADD `id` MEDIUMINT( 8 ) NOT NULL FIRST; 3,设置新主键: ALTER TABLE `table_nam......

niithub
51分钟前
0
0
福利篇:免费csdn vip账号分享

分享一个发布免费csdn vip账号的网站:啰嗦vip www.lostvip.com , 各种软件开发类的视频教程:慕课网、动脑学院、黑马各大培训机构VIP视频教程,非常不错!

在水一方发盐人
58分钟前
0
0
Nginx+Tomcat搭建高性能负载均衡集群

一、 工具   nginx-1.8.0   apache-tomcat-6.0.33 二、 目标   实现高性能负载均衡的Tomcat集群:    三、 步骤   1、首先下载Nginx,要下载稳定版:      2、然后解压两个Tom...

码代码的小司机
59分钟前
0
0
Centos7编译安装ntp-4.2.8p11

Centos7编译安装ntp-4.2.8p11 背景 因公司做等保评级,在进行安全漏洞检测时发现ntp需要升级到ntp-4.2.7p25以上版本,经过一番搜索,没有该版本及新版本ntp的yum安装包,所以只能编译安装了,...

阿dai
今天
0
0
antd pro 新增模块的步骤

index.js是整个项目的入口文件。 // 1. Initializeconst app = dva({ history: createHistory(),});// 2. Pluginsapp.use(createLoading());// 3. Register global modelapp.model......

灯下草虫鸣_
今天
0
0
Cisco VPN在win10下报Error 56的解决办法

问题描述 Cisco VPN在win10下报Error 56: The Cisco Systems, Inc. VPN Service has not been started 解决方案 方案一:在计算机管理-》服务 查看Cisco Systems, Inc. VPN Service服务是否存...

chenfj_fer
今天
0
0
Weblogic问题解决记录

问题:点击登录,页面刷新但是不进去管理界面。解决:删除cookies再登录。

wffger
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部