我是如何一步步编码完成万仓网ERP系统的(四)登录的具体实现
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构)
https://www.cnblogs.com/smh188/p/11534451.html(我是如何一步步编码完成万仓网ERP系统的(二)前端框架)
https://www.cnblogs.com/smh188/p/11535449.html(我是如何一步步编码完成万仓网ERP系统的(三)登录)
https://www.cnblogs.com/smh188/p/11541033.html(我是如何一步步编码完成万仓网ERP系统的(四)登录的具体实现)
https://www.cnblogs.com/smh188/p/11542310.html(我是如何一步步编码完成万仓网ERP系统的(五)产品库设计 1.产品类别)
https://www.cnblogs.com/smh188/p/11546917.html(我是如何一步步编码完成万仓网ERP系统的(六)产品库设计 2.百度Ueditor编辑器)
https://www.cnblogs.com/smh188/p/11572668.html(我是如何一步步编码完成万仓网ERP系统的(七)产品库设计 3.品牌图片跨域上传)
https://www.cnblogs.com/smh188/p/11576543.html(我是如何一步步编码完成万仓网ERP系统的(八)产品库设计 4.品牌类别)
https://www.cnblogs.com/smh188/p/11578185.html(我是如何一步步编码完成万仓网ERP系统的(九)产品库设计 5.产品属性项)
https://www.cnblogs.com/smh188/p/11589264.html(我是如何一步步编码完成万仓网ERP系统的(十)产品库设计 6.属性项和类别关联)
https://www.cnblogs.com/smh188/p/11596459.html(我是如何一步步编码完成万仓网ERP系统的(十一)产品库设计 7.发布商品)
https://www.cnblogs.com/smh188/p/11610960.html(我是如何一步步编码完成万仓网ERP系统的(十二)库存 1.概述)
https://www.cnblogs.com/smh188/p/11669871.html(我是如何一步步编码完成万仓网ERP系统的(十三)库存 2.加权平均价)
https://www.cnblogs.com/smh188/p/11763319.html(我是如何一步步编码完成万仓网ERP系统的(十四)库存 3.库存日志)
万仓网ERP系统不开源,准备做一个系列,讲一讲主要的技术点,这些技术点会有源代码。如果想看所有的源代码,可以打道回府了,没必要再阅读下去了,浪费您宝贵的时间。
上一篇咱们讲了用户登录的简单实现,偏重于加密解密方面,这一篇咱们就接着上篇的来,在后台解密得到login对象时,如何根据login对象的UserName查询出数据库中的用户。
这就要结合第一篇文章系统架构来说。
首先要在ZJ.Domain层,声明一个Domain用户对象,当然实际的用户对象不可能就这4个字段,在这里咱们只做示例使用。
[Serializable]
public class EmployeeDomain
{
//用户名
public string EmployeeId { get; set; }
//用户编号
public long EmployeeNo { get; set; }
//密码
public string PassWord { get; set; }
//姓名
public string EmployeeName { get; set; }
}
第二步,在ZJ.Repository层,声明一个根据用户名查询的接口,返回用户Domain对象。
public interface IEmployeeRepository
{
/// <summary>
/// 获取一个员工明细
/// </summary>
/// <returns></returns>
EmployeeDomain GetEmployeeById(string employeeId);
}
第三步,在ZJ.Repository.Core和ZJ.Repository.MySqlCore层实现ZJ.Repository层的接口,如果无特殊说明,代码都是以ZJ.Repository.Core为主,ZJ.Repository.MySqlCore和ZJ.Repository.Core差不多,就不在贴了。ZJ.Repository.Core没有用EF等一些实体类框架,本文也不讨论EF实体框架和SQL语句的优劣,万仓网ERP系统的ZJ.Repository.Core层都是SQL语句。
public class EmployeeRepository : SqlServerDao, IEmployeeRepository
{
/// <summary>
/// 获取一个员工明细
/// </summary>
/// <returns></returns>
public EmployeeDomain GetEmployeeById(string employeeId)
{
string sql = @"SELECT * FROM Employee( NOLOCK ) where EmployeeId=@EmployeeId";
IList<SqlParameter> sqlParams = new List<SqlParameter>
{
new SqlParameter()
{
ParameterName ="@EmployeeId",
SqlDbType=SqlDbType.VarChar,
Size=,
Value = employeeId
}
};
DataTable dt = SqlHelper.ExecuteDataset(DefaultExecuteConnString, CommandType.Text, sql, sqlParams.ToArray()).Tables[];
if (dt != null && dt.Rows.Count > )
{
//将DataTable的Row转换为EmployeeDomain对象
return dt.Rows[].ToEntity<EmployeeDomain>();
}
return new EmployeeDomain();
}
}
第四步,在ZJ.Services层,声明一个根据用户名查询的接口,返回用户Domain对象,同ZJ.Repository层的接口。
public interface IEmployeeService
{
/// <summary>
/// 获取一个员工明细
/// </summary>
/// <returns></returns>
EmployeeDomain GetEmployeeById(string employeeId);
}
第五步,在ZJ.Services.Impl层,实现ZJ.Services层的接口。在这一层你会看到用得是ZJ.Repository接口,怎么回事,这样就能调通ZJ.Repository.Core的实现吗(稍后你会看到接口层和实现层怎么关联起来)?
public class EmployeeService : IEmployeeService
{
private readonly IEmployeeRepository _employeeRepository; public EmployeeService(IEmployeeRepository employeeRepository)
{
_employeeRepository = employeeRepository;
} /// <summary>
/// 获取一个员工明细
/// </summary>
/// <returns></returns>
public EmployeeDomain GetEmployeeById(string employeeId)
{
return _employeeRepository.GetEmployeeById(employeeId);
}
}
第六步,在ZJ.BLL写业务逻辑。
public class EmployeeBLL
{
private static readonly IEmployeeService _employeeService = ServiceLocator.Instance.GetService<IEmployeeService>(); /// <summary>
/// 获取一个员工明细
/// </summary>
/// <returns></returns>
public EmployeeDomain GetEmployeeById(string employeeId)
{
//一堆业务逻辑
//各种判断等可以在BLL层,这里咱们就简单点,直接调用ZJ.Services层的接口
return _employeeService.GetEmployeeById(employeeId);
}
}
上一步咱们用到了ZJ.Infrastructure层的一个类ServiceLocator,基于Microsoft.Practices.Unity的控制反转,具体咱们就直接上代码吧。
/// <summary>
/// Represents the Service Locator.
/// </summary>
public sealed class ServiceLocator : IServiceProvider
{
#region Private Fields private readonly IUnityContainer _container; #endregion #region Private Static Fields // ReSharper disable InconsistentNaming
private static readonly ServiceLocator instance = new ServiceLocator();
// ReSharper restore InconsistentNaming #endregion #region Ctor /// <summary>
/// Initializes a new instance of <c>ServiceLocator</c> class.
/// </summary>
private ServiceLocator()
{
UnityConfigurationSection section = (UnityConfigurationSection) ConfigurationManager.GetSection("unity");
_container = new UnityContainer();
section.Configure(_container);
} #endregion #region Public Static Properties /// <summary>
/// Gets the singleton instance of the <c>ServiceLocator</c> class.
/// </summary>
public static ServiceLocator Instance
{
get { return instance; }
} #endregion #region Private Methods private IEnumerable<ParameterOverride> GetParameterOverrides(object overridedArguments)
{
List<ParameterOverride> overrides = new List<ParameterOverride>();
Type argumentsType = overridedArguments.GetType();
argumentsType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.ToList()
.ForEach(property =>
{
object propertyValue = property.GetValue(overridedArguments, null);
string propertyName = property.Name;
overrides.Add(new ParameterOverride(propertyName, propertyValue));
});
return overrides;
} #endregion #region Public Methods /// <summary>
/// Gets the service instance with the given type.
/// </summary>
/// <typeparam name="T">The type of the service.</typeparam>
/// <returns>The service instance.</returns>
public T GetService<T>()
{
return _container.Resolve<T>();
} public IEnumerable<T> ResolveAll<T>()
{
return _container.ResolveAll<T>();
} /// <summary>
/// Gets the service instance with the given type by using the overrided arguments.
/// </summary>
/// <typeparam name="T">The type of the service.</typeparam>
/// <param name="overridedArguments">The overrided arguments.</param>
/// <returns>The service instance.</returns>
public T GetService<T>(object overridedArguments)
{
IEnumerable<ParameterOverride> overrides = GetParameterOverrides(overridedArguments);
// ReSharper disable CoVariantArrayConversion
return _container.Resolve<T>(overrides.ToArray());
// ReSharper restore CoVariantArrayConversion
} /// <summary>
/// Gets the service instance with the given type by using the overrided arguments.
/// </summary>
/// <param name="serviceType">The type of the service.</param>
/// <param name="overridedArguments">The overrided arguments.</param>
/// <returns>The service instance.</returns>
public object GetService(Type serviceType, object overridedArguments)
{
IEnumerable<ParameterOverride> overrides = GetParameterOverrides(overridedArguments);
// ReSharper disable CoVariantArrayConversion
return _container.Resolve(serviceType, overrides.ToArray());
// ReSharper restore CoVariantArrayConversion
} #endregion #region IServiceProvider Members /// <summary>
/// Gets the service instance with the given type.
/// </summary>
/// <param name="serviceType">The type of the service.</param>
/// <returns>The service instance.</returns>
public object GetService(Type serviceType)
{
return _container.Resolve(serviceType);
} #endregion
}
这样基本代码就写完了,留了个尾巴,接口层如何和实现层结合起来,可以使用Unity的配置文件(也可以编写代码),放在网站的根目录下。
<?xml version="1.0" encoding="utf-8"?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="ZJ.Repository.UserInfo.IEmployeeRepository, ZJ.Repository"
mapTo="ZJ.Repository.Core.UserInfo.EmployeeRepository, ZJ.Repository.Core" >
<lifetime type="singleton"/>
</register>
<register type="ZJ.Services.UserInfo.IEmployeeService, ZJ.Services"
mapTo="ZJ.Services.Impl.UserInfo.EmployeeService, ZJ.Services.Impl" >
<lifetime type="singleton"/>
</register>
</container>
</unity>
web.config中配置了系统基于什么类型的数据库(sql server或mysql),如果是mysql数据库要使用基于mysql的unity配置。
<?xml version="1.0" encoding="utf-8"?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="ZJ.Repository.UserInfo.IEmployeeRepository, ZJ.Repository"
mapTo="ZJ.Repository.MySqlCore.UserInfo.EmployeeRepository, ZJ.Repository.MySqlCore" >
<lifetime type="singleton"/>
</register>
<register type="ZJ.Services.UserInfo.IEmployeeService, ZJ.Services"
mapTo="ZJ.Services.Impl.UserInfo.EmployeeService, ZJ.Services.Impl" >
<lifetime type="singleton"/>
</register>
</container>
</unity>
同时在web.config中要引用unity的配置文件。
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity configSource="Unity.config" />
好,终于大功告成了,可以在Controller中引用ZJ.BLL层中的EmployeeBLL类了。
private readonly EmployeeBLL employeeBLL = new EmployeeBLL();
employeeBLL.GetEmployeeById(userName);
有兴趣的朋友可以自己搭个测试项目,敲敲代码。
PS:客官有时间光临我的小站 万仓网
我是如何一步步编码完成万仓网ERP系统的(四)登录的具体实现的更多相关文章
- 我是如何一步步编码完成万仓网ERP系统的(一)系统架构
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(二)前端框架
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(三)登录
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(五)产品库设计 1.产品类别
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(六)产品库设计 2.百度Ueditor编辑器
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(七)产品库设计 3.品牌图片跨域上传
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(八)产品库设计 4.品牌类别
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(九)产品库设计 5.产品属性项
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 我是如何一步步编码完成万仓网ERP系统的(十)产品库设计 6.属性项和类别关联
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
随机推荐
- 【微信错误】{"errcode":"40013","errmsg":"invalid appid hint: [mackRA06203114]","success":false}
一.异常背景 发送可以跳转小程序的公众号模版消息 二.原因 当前公众号没有和被跳转的小程序关联 三.解决办法 去公众号平台将小程序和公众号进行关联就可以了
- HTML与CSS学习笔记(2)
1.CSS背景样式? background-color 背景色 background-image 背景图 url(背景地址) 默认:会水平垂直铺满背景图 background-repeat 平铺方式 ...
- JVM 启动参数,共分为3类
JVM 启动参数,共分为3类: 类别 说明 标准参数(-) 所有的JVM实现都必须实现这些参数的功能,而且向后兼容: 非标准参数(-X) 这些参数不是虚拟机规范规定的.因此,不是所有VM的实现(如:H ...
- SpringBoot设置支持跨域请求
跨域:现代浏览器出全的考虑,在http/https请求时必须遵守同源策略,否则即使跨域的http/https 请求,默认情况下是被禁止的,ip(域名)不同.或者端口不同.协议不同(比如http.htt ...
- JDOJ 2898 删数问题
洛谷 P1106 删数问题 https://www.luogu.org/problemnew/show/P1106 JDOJ 2898: 删数问题 https://neooj.com:8082/old ...
- USACO Cow Cars
洛谷 P2909 [USACO08OPEN]牛的车Cow Cars https://www.luogu.org/problemnew/show/P2909 JDOJ 2584: USACO 2008 ...
- 遵循PEP8风格
遵循PEP8风格 在编写python代码的时候我们应该采用统一的风格来编写代码,可以使代码更加容易读懂.采用和其他程序员统一的编码风格来写代码,也可以使项目更利于多人协作开发.即便代码只有你自己能看懂 ...
- Codeforces Round #549 (Div. 2) E 倍增处理按排列顺序的上一个位置
https://codeforces.com/contest/1143/problem/E 题意 p为n的一个排列,给出有m个数字的数组a,q次询问,每次询问a数组区间[l,r]中是否存在子序列为p的 ...
- python的小数据池
一.什么是小数据池? 小数据池是一种缓存机制,也被称为驻留机制.各种编程语言中都有类似的东西(常量池.小数据池都是指得同一个内容). python自动将-5~256的整数.有一定规则的字符串.都放在一 ...
- MySQL实战45讲学习笔记:第二十六讲
一.引子 在上一篇文章中,我和你介绍了几种可能导致备库延迟的原因.你会发现,这些场景里,不论是偶发性的查询压力,还是备份,对备库延迟的影响一般是分钟级的,而且在备库恢复正常以后都能够追上来. 但是,如 ...