本人小白,写博客主要是记录本人学习c#的有关历程,有可以参考的同学也可以参考学习,有关代码如涉及侵权请联系删除,谢谢。
简介:本人计算机专业,个人在校期间学习的主动性不够,属于老师教什么就学习什么的类型(这点希望后面的大学生能够在学校期间,主动学习该领域就业的新知识),毕业后从事软件测试,目前从事工作与编程基本无关。
在校期间主要学习了c#基础语法,ajax网络通信技术听说过,但不是很了解。
再次学习c#目的:现在工作归纳总结留痕的较多,现在想利用空余时间编写一个综合管理系统,用于记录工作有关信息,本来想直接学习.net8的,看了有关学习视频,基础太薄弱了,很多都不懂,只有先从winform入手了。
1、学习三层架构。以前老是听说,个人理解就是在同一个解决方案中,多建几个类库,每个类库实现各自的功能。如下图:
(1)hrms是主要程序。里面的Program是应用程序的主入口点,可以配置程序开始时,启动的winform窗体,里面可以自己建很多winform窗体。
internal static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new loginform());//loginform就是我程序的启动窗体
}
}
(2)model:就是实体,对应的是数据库里面的每一个表,比如下面我会用到登陆用户信息表(BaseUser),就会在这个类库中建一个对应的model实体,其余几个都是我会用到的,不一一举例,BaseUser代码如下:
//这是model中的代码,与数据表格式对应
public class BaseUser
{ public int BaseUserid { get; set; }
public string BaseUsername { get; set; }
public string BaseUserrealname { get; set; }
public string BaseUserpwd { get; set; }
public string BaseUsercreatedate { get; set; }
}
//这是数据库创建此表的代码,与model对应
/************* 1.创建登录人员信息表****************/
create table BaseUser
(
BaseUserid int IDENTITY(1,1) PRIMARY KEY, /* 自增序号 */
BaseUsername varchar(255), /* 用户名 */
BaseUserrealname varchar(255), /* 真实姓名 */
BaseUserpwd varchar(255), /* 密码 */
BaseUsercreatedate datetime /* 创建时间 */
)
(3)DBUtility:这个类库中新建了SqlHelper类,主要存放数据库连接和增、删、改、查方法,后续程序只需要在这里调用对应的方法,就可以返回相应数据,太香了(主要是从某音看的:繁體記憶 老师的视频)。
namespace DBUtility
{
public class SqlHelper
{
//这里是调用配置文件中的连接字符串
public static string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;//连接字符串
private static int result = 0;
///查询是否存在,调用此语句,返回查询的第一行第一列数据,我主要搭count语句使用。例如:SELECT COUNT(*) FROM Table
public static int Getsingle(string sql, params SqlParameter[] para)
{
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlCommand cmd = new SqlCommand(sql, conn);
if (conn.State == ConnectionState.Closed)
{
conn.Open(); //打开数据库
}
if (para != null && para.Length > 0)
{
cmd.Parameters.Clear(); //清空上一个数据
cmd.Parameters.AddRange(para);
}
result= Convert.ToInt32(cmd.ExecuteScalar());
return result;
}
}
//用于执行不返回结果集的SQL语句或存储过程,如INSERT、UPDATE、DELETE 等操作
//它返回受影响的行数,即执行SQL语句后所影响的行数
public static int WriteDB(string sql,params SqlParameter[] para)
{
SqlConnection conn =new SqlConnection(connStr);
try
{
if (conn.State == ConnectionState.Closed)
{
conn.Open(); //打开数据库
}
SqlCommand cmd =new SqlCommand(sql,conn);
if (para != null && para.Length > 0)
{
cmd.Parameters.Clear(); //清空上一个数据
cmd.Parameters.AddRange(para);
}
//执行sql语句
result= Convert.ToInt32(cmd.ExecuteNonQuery());
}
catch(Exception ex)
{
//如果有必要在这里写个记录日志
string errorMessage = "调用ExecuteNonQuery方法发生异常:"+ex.Message;
throw new Exception(errorMessage);
}
finally
{
conn.Close();
}
return result;
}
//个人理解,这个是返回数据表
public static DataTable getDateTable(string sql, params SqlParameter[] parms)
{
using (SqlDataAdapter adapter = new SqlDataAdapter(sql, connStr))
{
DataTable dt = new DataTable();
if (parms != null)
{
adapter.SelectCommand.Parameters.AddRange(parms);
}
adapter.Fill(dt);
return dt;
}
}
}
}
(4)Common存放通用功能,主要建了两个类:Encrytion.cs 用于数据加密、SerializeObject.cs用于序列化(这个项目我主要用于把图片序列化成文本存放于数据库,数据库读出来反序列化成图片显示)
//Encrytion.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//导入此库
using System.Security.Cryptography;
using System.IO;
namespace Common
{
public class Encrytion
{
public string GetMd5x(string inputStr)
{
//创建md5对象
MD5 md5 = MD5.Create();
//现将字符串转换为数组,再开始加密
byte[] buffer = Encoding.Default.GetBytes(inputStr);
//加密,返回一个加密好的字节数组
byte[] Md5Buffer = md5.ComputeHash(buffer);
//将字节数组转换成字符串
string newstr = "";
for (int i = 0; i < Md5Buffer.Length; i++)
{
newstr += Md5Buffer[i].ToString("x");
}
return newstr;
}
public string GetMd5x2(string inputStr)
{
//创建md5对象
MD5 md5 = MD5.Create();
//现将字符串转换为数组,再开始加密
byte[] buffer = Encoding.Default.GetBytes(inputStr);
byte[] Md5Buffer = md5.ComputeHash(buffer);
//将字节数组转换成字符串
string str = "";
for (int i = 0; i < Md5Buffer.Length; i++)
{
str += Md5Buffer[i].ToString("x2");
}
return str;
}
}
}
//SerializeObject.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//引入三个命名空间
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace Common
{
public class SerializeObject
{
#region ObjectTostring
将Object类型对象(注:必须是可序列化的对象)转换为二进制序列字符串
public string SerializeObjectToString(object obj)
{
IFormatter formatter = new BinaryFormatter();
string result = string.Empty;
using (MemoryStream stream = new MemoryStream())
{
formatter.Serialize(stream, obj);
byte[] byt = new byte[stream.Length];
byt = stream.ToArray();
result = Convert.ToBase64String(byt);
stream.Flush();
}
return result;
}
#endregion
#region tringTosObject
//将二进制序列字符串转换为Object类型对象
public object DeserializeObjectFromString(string str)
{
IFormatter formatter = new BinaryFormatter();
byte[] byt = Convert.FromBase64String(str);
object obj = null;
using (Stream stream = new MemoryStream(byt, 0, byt.Length))
{
obj = formatter.Deserialize(stream);
}
return obj;
}
#endregion
}
}
最后再说连接字符串,是在主程序类库中的App.config中的<configuration>节点下新增 <connectionStrings>节点,具体如下:
<connectionStrings>
<add name="connStr" connectionString="server=.;database=HRMSDBB;uid=sa;pwd=123456" />
</connectionStrings>
到这里,程序架构基本完成,另外需要说明的是,正规的应该还要建BLL类库(业务逻辑层,里面建Loginmanager,名字可自行修改,主要用于调用数据访问层,判断是否登陆成功)、DAL类库(数据访问层,里面建Loginserver类,可根据自己情况命名,主要用于实现调用数据库,DBUtility的对应方法)
下面是登陆的整个流程:
//登陆winform窗体的 确定按钮,代码:
private void buttonlogin_Click(object sender, EventArgs e)
{
//用户名、密码非空判断。这个代码是用的express,所以textbox、messagebox名字是textEditusername、XtraMessageBox。
if (textEditusername.Text.Length==0)
{
XtraMessageBox.Show("用户名为空,请输入用户名!", "登录提示");
textEditusername.Focus();
return;
}
if (textEditpwd.Text.Length==0)
{
XtraMessageBox.Show("密码为空,请输入密码!", "登录提示");
textEditpwd.Focus();
return;
}
//封装对象。以前老是听说封装,感觉好高大上,结果就是这样的,嘿嘿。
BaseUser baseUser = new BaseUser()
{
BaseUsername = textEditusername.Text.Trim(),
BaseUserpwd = textEditpwd.Text
};
//提交数据
try
{
//创建业务逻辑层中的LoginManager类对象,用于调用其中的登陆方法。因为登陆界面要调用业务逻辑层,所有在这里要添加引用,引用BLL类库。
LoginManager loginManager = new LoginManager();
int i = loginManager.Login(baseUser);
if (i != 1)
{
XtraMessageBox.Show("用户名或密码错误!", "登录提示");
}
else
{
this.Hide();
RibbonFormMain ribbonFormMain = new RibbonFormMain();
ribbonFormMain.Show();
}
}
catch(Exception ex)
{
XtraMessageBox.Show(ex.Message);
}
}
//BLL业务逻辑层,中的login方法代码如下,我写得比较简单,按理说登陆是否成功应该在这里判断是否成功,我弄到界面那里判断了,小白的思维体现无疑。
public int Login(BaseUser objBaseUser)
{
//这里创建DAL数据访问层对象,用于访问数据库
LoginServer dal = new LoginServer();
return dal.Login(objBaseUser);
}
//DAL类库中Login方法代码:
public int Login(BaseUser objBaseUser)
{
string sql = "SELECT COUNT(*) FROM BaseUser WHERE BaseUsername=@BaseUsername AND BaseUserpwd=@BaseUserpwd";
SqlParameter[] para = new SqlParameter[]
{
new SqlParameter("@BaseUsername",objBaseUser.BaseUsername),
new SqlParameter("@BaseUserpwd",objBaseUser.BaseUserpwd),
};
//这里调用DBUtility类库中的Getsingle方法,判断是否有此条数据
return SqlHelper.Getsingle(sql, para);
}
//DBUtility类库中的Getsingle方法代码,执行数据库操作方法ExecuteScalar,返回第一行第一列的值
public static int Getsingle(string sql, params SqlParameter[] para)
{
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlCommand cmd = new SqlCommand(sql, conn);
if (conn.State == ConnectionState.Closed)
{
conn.Open(); //打开数据库
}
if (para != null && para.Length > 0)
{
cmd.Parameters.Clear(); //清空上一个数据
cmd.Parameters.AddRange(para);
}
//执行ExecuteScalar方法,返回第一行第一列的值
result= Convert.ToInt32(cmd.ExecuteScalar());
return result;
}
}