[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言

时间:2021-03-17 05:22:39

前言:                                                 

关于不同框架实现同一个TaskVision:

前面DebugLZQ先是用WPF(没有使用MVVM,因为前面使用MVVM实现过过点餐系统),因而这个关键点就放在了WPF的Binding上面;

然后用普通的Winform,没有加入任何模式,实现了相同的功能。因此这个重点放在了DataGridView的总结,以及WinForm自定义控件实现类似WPF控件上面。

本篇博文使用标准的三层架构,重新实现这个TaskVision。因而重点放在三层架构方面、为了体现三层的各层间低耦合的特点,博文下半部分会将DAL换成WebService,并实现多语言。数据库依然是原来的SQL Server 2008.

标准的是这样的:                                         

在软件体系设计中,分层式结构式最常见也是最重要的一种结构。MS推荐的分层结构一般分为三层,从上到下依次为UI、BLL、DAL。

理解软件分层的概念有助于理解各种大量应用的模式结构,如MVC、MVVM等。以及GOF其他的一些等等。理解了三层,其他的理解起来会方便很多,因为其中贯通的都是:表现层的解耦。个人理解:模式间的区别是:根据具体的技术框架特点,决定表现层解耦方法的不同,由不断的最佳实践,总结出了各种不同的模式。即前面DebugLZQ也说的:表现层的持续解耦,带来的模式的转变!

传统的三层式这样的:

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言

解释一下:UI层调用BLL层,传递的参数为UI层控件的属性值;BLL层调用DAL层,并加入相应的逻辑;DAL层则负责对数据库访问的封装(DAL层直接封装数据库访问,箭头所示)。

我理解的规则

1.UI层不包括任何BL;

2.设计从BLL出发,而不是从UI出发,BLL实现所有的BL。

3.DAL应该做到一定程度上与系统无关。即这一层可抽离。

4.不可跨层调用;

满足以上规则,就可以认为这个项目是三层了。

(*给出的)优点

  1、开发人员可以只关注整个结构中的其中某一层;
  2、可以很容易的用新的实现来替换原有层次的实现;
  3、可以降低层与层之间的依赖;
  4、有利于标准化;
  5、利于各层逻辑的复用。
  6、结构更加的明确
  7、在后期维护的时候,极大地降低了维护成本和维护时间
(*给出的)缺点
  1、降低了系统的性能。这是不言而喻的。如果不采用分层式结构,很多业务可以直接造访数据库,以此获取相应的数据,如今却必须通过中间层来完成。
  2、有时会导致级联的修改。这种修改尤其体现在自上而下的方向。如果在表示层中需要增加一个功能,为保证其设计符合分层式结构,可能需要在相应的业务逻辑层和数据访问层中都增加相应的代码。
  3、增加了开发成本。
关于引用百科的解释:确实是这样,不需要我去另外理解、解释。但是关于模式的理解是个人的。 

 实际是这样的                             

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言
实际使用中通常会
1.加入Model。Model用来作为参数,在UI和BLL间传递。耦合度进一步降低!
2.将DAL直接访问数据库改成调用其他数据库访问类库或服务,耦合度进一步降低!
因此,针对DebugLZQ这个版本的TaskVison,你看到的所谓三层可能是这样的“5层”。如下:
[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言
各层代码如下,以登陆为例:
UI:Login.cs
[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言View Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Models;

namespace TaskVision_V2
{
public partial class Login : Form
{
public Login()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
Models.UserLoginModel userLoginModel
= new UserLoginModel() { UserName=txtUserName.Text.Trim(), Password=txtPassword.Text, RememberPassword=checkBox1.Checked};
if (BLL.UserService.Login(userLoginModel))
{
//FormMain formMain = new FormMain();
//formMain.Show();
Global.userName = txtUserName.Text;
this.DialogResult = DialogResult.OK;
}
else
{
MessageBox.Show(
"用户名或密码错误!");
}
}

private void button2_Click(object sender, EventArgs e)
{
this.Close();
}
}
}

Models:UserLoginModel.cs(叫UserModel更贴切,Model对应数据库表+判断逻辑控件value)

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Models
{
public class UserLoginModel
{
public string Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public bool RememberPassword { get; set; }
}
}

BLL:UserService.cs

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;

namespace BLL
{
public class UserService
{
/// <summary>
/// User Login
/// </summary>
private static string loginSQLText = "select * from tb_UserInfo where UserName=@UserName and Password=@Password";
public static bool Login(Models.UserLoginModel userLoginModel)
{
if (userLoginModel.RememberPassword)
{
//todo:
}
SqlParameter[] parameters
= new SqlParameter[] { new SqlParameter("@UserName",userLoginModel.UserName),new SqlParameter("@Password",userLoginModel.Password)};
return DAL.DataAccess.ExecuteReader(loginSQLText, parameters);
}
/// <summary>
/// Get All User
/// </summary>
private static string getUserSQLText = "select distinct UserName from tb_UserInfo";
public static DataTable GetUser()
{
return DAL.DataAccess.GetDataTable(getUserSQLText);
}
}
}

DAL:DataAccess.cs

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace DAL
{
public static class DataAccess
{
public static DataTable GetDataTable(string sqlText, params SqlParameter[] parameters)
{
return AdoDotNetClassLibrary.SQLHelper.GetDataTable(sqlText, parameters);
}

public static int ExecuteNonQuery(string sqlText,params SqlParameter[] parameters)
{
return AdoDotNetClassLibrary.SQLHelper.ExecuteNonQuery(sqlText,parameters);
}

public static bool ExecuteReader(string sqlText, SqlParameter[] parameters)
{
return AdoDotNetClassLibrary.SQLHelper.ExecuteReader(sqlText, parameters);
}
}
}

AdoDotNetClassLibrary:SQLHelper.cs

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言
using System.Data;
using System.Data.SqlClient;

namespace AdoDotNetClassLibrary
{
public static class SQLHelper
{
public const string connectionString = @"server=LocalHost;database=TaskVision;Trusted_Connection=SSPI";

public static DataTable GetDataTable(string sqlText,params SqlParameter[] parameters)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlDataAdapter sda
= new SqlDataAdapter(sqlText, conn);
foreach (SqlParameter parameter in parameters)
{
sda.SelectCommand.Parameters.Add(parameter);
}
DataTable dt
= new DataTable();
sda.Fill(dt);

return dt;
}
}

public static int ExecuteNonQuery(string sqlText,params SqlParameter[] parameters)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlCommand cmd
= new SqlCommand(sqlText, conn);
foreach (SqlParameter parameter in parameters)
{
cmd.Parameters.Add(parameter);
}
conn.Open();
int temp = cmd.ExecuteNonQuery();
return temp;
}
}

public static bool ExecuteReader(string sqlText, params SqlParameter[] parameters)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd
= new SqlCommand(sqlText, conn);
foreach (SqlParameter parameter in parameters)
{
cmd.Parameters.Add(parameter);
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
return true;
return false;
}
}
}

}
}
View Code

数据由Webservice提供                   

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言

注意点:

由于webservice序列化问题,SqlParameter不能直接传递,因此改用strng代替下;

http://forums.asp.net/t/1335298.aspx!需要为DataTable设置名称,dt.TableName="myTable";

需要将DAL引用webservice生成的config文件拷贝到UI工程中(注意:不是webservice项目的config)。否则会报告无法找到EndPoint运行时错误。

由此只要:

添加:AdoDotNetWebService--service1.asmx 

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data;
using System.Data.SqlClient;
using System.Collections;

namespace AdoDotNetWebService
{
/// <summary>
/// Summary description for Service1
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo
= WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(
false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class Service1 : System.Web.Services.WebService
{

[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
public const string connectionString = @"server=LocalHost;database=TaskVision;Trusted_Connection=SSPI";


[WebMethod]
public DataTable GetDataTable(string sqlText, params string[] parameters)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlDataAdapter sda
= new SqlDataAdapter(sqlText, conn);
for(int i=0;i<parameters.Length;i=i+2)
{
sda.SelectCommand.Parameters.Add(
new SqlParameter(parameters[i],parameters[i+1]));
}
DataTable dt
= new DataTable();
dt.TableName
= "MyTable";//OMG!
sda.Fill(dt);

return dt;
}
}

[WebMethod]
public int ExecuteNonQuery(string sqlText, params string[] parameters)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlCommand cmd
= new SqlCommand(sqlText, conn);
for (int i = 0; i < parameters.Length; i = i + 2)
{
cmd.Parameters.Add(
new SqlParameter(parameters[i],parameters[i+1]));
}
conn.Open();
int temp = cmd.ExecuteNonQuery();
return temp;
}
}



[WebMethod]
public bool ExecuteReader(string sqlText, params string[] parameters)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd
= new SqlCommand(sqlText, conn);
for (int i = 0; i < parameters.Length; i = i + 2)
{
cmd.Parameters.Add(
new SqlParameter(parameters[i], parameters[i + 1]));
}
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
return true;
return false;
}
}
}
}
}

修改DAL:

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Collections;

namespace DAL
{
public static class DataAccess
{
//webserviceclient
public static ServiceReference1.Service1SoapClient client = new ServiceReference1.Service1SoapClient();

public static DataTable GetDataTable(string sqlText, params SqlParameter[] parameters)
{
//return AdoDotNetClassLibrary.SQLHelper.GetDataTable(sqlText, parameters);
ArrayList ps = new ArrayList();
for (int i = 0; i < parameters.Length; i++)
{
ps.Add(parameters[i].ParameterName);
ps.Add(parameters[i].Value);
}
string[] ps1 = (string[])ps.ToArray(typeof(string));
return client.GetDataTable(sqlText, ps1);
}

public static int ExecuteNonQuery(string sqlText, params SqlParameter[] parameters)
{
//return AdoDotNetClassLibrary.SQLHelper.ExecuteNonQuery(sqlText,parameters);

ArrayList ps
= new ArrayList();
for (int i = 0; i < parameters.Length; i++)
{
ps.Add(parameters[i].ParameterName);
ps.Add(parameters[i].Value);
}
string[] ps1 = (string[])ps.ToArray(typeof(string));
return client.ExecuteNonQuery(sqlText, ps1);
}



public static bool ExecuteReader(string sqlText, params SqlParameter[] parameters)
{
//return AdoDotNetClassLibrary.SQLHelper.ExecuteReader(sqlText, parameters);

ArrayList ps
= new ArrayList();
for (int i = 0; i < parameters.Length; i++)
{
ps.Add(parameters[i].ParameterName);
ps.Add(parameters[i].Value);
}
string[] ps1 = (string[])ps.ToArray(typeof(string));

return client.ExecuteReader(sqlText, ps1);
}
}
}

其他层保持不变!

 实现多语言                           

 非常简单。步骤如下:

1.设置Form的Localizable属性为True。
2.为每个Form添加对应的资源文件,命名有要求:以Login.cs窗体为例,资源名为Login.en.resx/Login.zh-CHS.resx(需要查阅具体语言的代码)。添加完成后VS自动将该资源文件添加到对应的窗体下。
3.编辑添加的资源文件,注意:不同String类型资源文件的Name在不同的resx中必须相同。目的是为了保证编码方便。
4.在Form_Load中根据CurrentUICulture为 Form的控件Text赋值(是用的是resx中string的Name,赋的是Value)

以Login为例。

1.设置Localizable属性为True。

2.添加资源文件:

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言

添加代码:

[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言View Code
        private void Login_Load(object sender, EventArgs e)
{
Thread.CurrentThread.CurrentUICulture
= new System.Globalization.CultureInfo("en");
UpDataMainFormUILanguage();
}

private void UpDataMainFormUILanguage()
{
ResourceManager rm
= new ResourceManager(typeof(Login));
UpdateLoginUILanguage(rm);
}

private void UpdateLoginUILanguage(ResourceManager rm)
{
this.Text = rm.GetString("Login");
lblUserName.Text
= rm.GetString("UserName");
lblPassword.Text
= rm.GetString("Password");
checkBox1.Text
= rm.GetString("RememberPassword");
btnLogin.Text
= rm.GetString("Login");
btnCancel.Text
= rm.GetString("Cancel");
}

效果如下:
[.NET 三层架构(ADO.NET)+Web Service+多语言]WinForm三层架构重新实现TaskVision,外加WebService提供数据和多语言

小结:     

博文重点在于说明三层架构:UI层构建Model,传递给BLL层,BLL层利用UI层传过来的Model的属性作为参数调用DAL层,DAL层是对具体数据库访问方式的封装,真正的数据库访问则由具体的类库、服务等提供。关于三层架构也许很多人的理解都可能不够标准,我是这么认为的。附加介绍了WebService作为数据库提供程序的方法,需要注意的地方。以及实现多语言的一种参考方法。

 感触:  

Baidu不靠谱!多问Google、多用英文问问题!