关于泛型接口的探讨

大家在用三层架构做开发的时候,是否有使用接口,使用接口的时候是否有类似这样的代码:

public interface IT_logs
    {
        #region  成员方法
        /// <summary>
        /// 得到最大ID
        /// </summary>
        int GetMaxId();
        /// <summary>
        /// 是否存在该记录
        /// </summary>
        bool Exists(int Id);
        /// <summary>
        /// 增加一条数据
        /// </summary>
        int Add(Maticsoft.Model.T_logs model);
        /// <summary>
        /// 更新一条数据
        /// </summary>
        bool Update(Maticsoft.Model.T_logs model);
        /// <summary>
        /// 删除一条数据
        /// </summary>
        bool Delete(int Id);
        bool DeleteList(string Idlist );
        /// <summary>
        /// 得到一个对象实体
        /// </summary>
        Maticsoft.Model.T_logs GetModel(int Id);
        Maticsoft.Model.T_logs DataRowToModel(DataRow row);
        /// <summary>
        /// 获得数据列表
        /// </summary>
        DataSet GetList(string strWhere);
        /// <summary>
        /// 获得前几行数据
        /// </summary>
        DataSet GetList(int Top,string strWhere,string filedOrder);
        int GetRecordCount(string strWhere);
        DataSet GetListByPage(string strWhere, string orderby, int startIndex, int endIndex);
        /// <summary>
        /// 根据分页获得数据列表
        /// </summary>
        //DataSet GetList(int PageSize,int PageIndex,string strWhere);
        #endregion  成员方法
        #region  MethodEx

        #endregion  MethodEx
    } 

然后每个每个表都有一个这样的接口代码,对比之后发现,这样的代码是不是很多重复呢?
那么有什么好的办法可以减少这样的重复代码???

我想到的是泛型,接口同样可以泛型,看下面这张图,IT_admin,IT_advs,IT_artClass......,它们内部代码几乎一模一样

如果我们写这样的一个泛型接口,那么这一个接口就代替了上面所有的Idal接口,并且你再增加表,也不需要添加Idal的接口文件了,是不是很爽?

public interface IOperate<T>
    {
        bool UpdateData(T entityData);//添加、编辑
        bool Delete(int Id);//根据ID号删除数据
        DataTable GetTable(string where, string orderBy, int pageIndex, int pageSize, out int recordCount);//返回数据表
        List<T> GetList(string sqlsStr);//返回LIST
        T GetDataById(int Id);//返回实体对象
    }

代码很简单,我就不多做解释了,然后我们用每个DAL去实现这个接口,就可以,这样就不需要去为每个DAL单写一个接口了,要知道,每个DAL里的操作90%都是相同的,当然,我们也可以扩展一些其它方法出来。

其实为每个表写DAL中,也是有功能可以抽象出来的,比如:删除,判断ID号是否存在,每个DAL所操作的表名,和表的主键,还有数据库操作对象,这些内容其实也可以抽象出来,所以我想到建立一个DALBASE的抽象类,提供一些虚方法,如果哪个DAL不一样,那就重写虚方法就可以了。所以有了下面这个类

public abstract class DalBase
    {
        protected string TableName { set; get; }
        protected string PkField { set; get; }

        protected Database da = DatabaseFactory.CreateDatabase();
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public virtual bool Delete(int Id)
        {
            var sqlStr = "delete from {0} where {1}[email protected]";
            sqlStr = string.Format(sqlStr, this.TableName, this.PkField);
            var command = da.GetSqlStringCommand(sqlStr);
            da.AddInParameter(command, "@Id", DbType.Int32, Id);
            return da.ExecuteNonQuery(command) > 0;
        }
       /// <summary>
       /// 判断是否存在
       /// </summary>
       /// <param name="Id"></param>
       /// <returns></returns>
        public virtual bool IsExists(int Id)
        {
            var sqlStr = "select count(*) from @TableName where @[email protected]";
            var command = da.GetSqlStringCommand(sqlStr);
            da.AddInParameter(command, "@TableName", DbType.String, this.TableName);
            da.AddInParameter(command, "@PkField", DbType.String, this.PkField);
            da.AddInParameter(command, "@Id", DbType.Int32, Id);
            var obj = da.ExecuteScalar(command);
            if (obj != null && !Convert.IsDBNull(obj))
            {
                return int.Parse(obj.ToString()) > 0;
            }
            return false;
        }

    }

那么DAL类的代码应该是怎么样?

public class AdminDal : DalBase, IOperate<AdminEntity>
    {

        public AdminDal()
        {
            this.TableName = "T_Admin";
            this.PkField = "Id";
        }
        /// <summary>
        /// 添加,编辑
        /// </summary>
        /// <param name="entityData"></param>
        /// <returns></returns>
        public bool UpdateData(AdminEntity entityData)
        {
            var sqlStr = string.Empty;
            DbCommand command;
            if (entityData.Id == 0)//添加
            {
                sqlStr = @"insert into {0}(UserName,UserPwd,Flag,PostTime) values(@UserName,@UserPwd,@Flag,@PostTime)";
                sqlStr = string.Format(sqlStr, this.TableName);
                command = da.GetSqlStringCommand(sqlStr);
            }
            else//编辑
            {
                sqlStr = @"update {0} set [email protected],[email protected],[email protected] where {1}[email protected]";
                sqlStr = string.Format(sqlStr, this.TableName, this.PkField);
                command = da.GetSqlStringCommand(sqlStr);
                da.AddInParameter(command, "@Id", DbType.Int32, entityData.Id);
            }
            da.AddInParameter(command, "@UserName", DbType.String, entityData.UserName);
            da.AddInParameter(command, "@UserPwd", DbType.String, entityData.UserPwd);
            da.AddInParameter(command, "@Flag", DbType.String, entityData.Flag);
            da.AddInParameter(command, "@PostTime", DbType.DateTime, entityData.PostTime);
            return da.ExecuteNonQuery(command) > 0;
        }

        public List<AdminEntity> GetList(string sqlStr)
        {
            var list = new List<AdminEntity>();
            var command = da.GetSqlStringCommand(sqlStr);
            var dt = da.ExecuteDataSet(command).Tables[0];
            if (dt != null && dt.Rows.Count > 0)
            {
                foreach (DataRow dr in dt.Rows)
                {
                    var entity = new AdminEntity()
                    {
                        Id = int.Parse(dr["Id"].ToString()),
                        UserName = dr["UserName"].ToString(),
                        UserPwd = dr["UserPwd"].ToString(),
                        Flag = dr["Flag"].ToString(),
                        PostTime = DateTime.Parse(dr["PostTime"].ToString())
                    };
                    list.Add(entity);
                }
            }
            return list;
        }
        //分页查询,需要SQL2005 以上的版本支持
        /*private const string DefaultSqlStr = @"
        SELECT * FROM (
            SELECT row_number() OVER({0}) as ROW_NUMBER,* FROM
            (
                SELECT *  FROM T_admin
                {1}
            ) as a
        ) as b WHERE ROW_NUMBER > {2} AND ROW_NUMBER <= {3}";
         */
        //分页查询
        private const string DefaultSqlStr = @"select top {0} * from {1} where {2} not in (select top {3} {4} from {5} where 1=1 {6} {7}) {8} {9} ";
        private const string DefaultSqlCount = @"select count(*)  FROM {0} where 1=1 {1}";
        public DataTable GetTable(string where, string orderBy, int pageIndex, int pageSize, out int recordCount)
        {
            var sql = String.Format(DefaultSqlCount, this.TableName, where);
            var obj = da.ExecuteScalar(CommandType.Text, sql);
            recordCount = 0;
            if (obj != null && !Convert.IsDBNull(obj))
            {
                recordCount = int.Parse(obj.ToString());//记录条数
            }
            pageIndex = pageIndex > 0 ? pageIndex : 1;//最小为1
            if (string.IsNullOrEmpty(orderBy))
            {
                orderBy = " order by " + this.PkField + " Desc";
            }
            sql = String.Format(DefaultSqlStr, pageSize, this.TableName, this.PkField, (pageIndex - 1) * pageSize, this.PkField, this.TableName, where, orderBy, where, orderBy);
            return da.ExecuteDataSet(CommandType.Text, sql).Tables[0];
        }
        public AdminEntity GetDataById(int Id)
        {
            var sqlStr = "select * from {0} where {1}[email protected]";
            sqlStr = string.Format(sqlStr, this.TableName, this.PkField);
            var command = da.GetSqlStringCommand(sqlStr);
            da.AddInParameter(command, "@Id", DbType.Int32, Id);
            var dt = da.ExecuteDataSet(command).Tables[0];
            if (dt != null && dt.Rows.Count > 0)
            {
                var dr = dt.Rows[0];
                var entity = new AdminEntity()

                {
                    Id = int.Parse(dr["Id"].ToString()),
                    UserName = dr["UserName"].ToString(),
                    UserPwd = dr["UserPwd"].ToString(),
                    Flag = dr["Flag"].ToString(),
                    PostTime = DateTime.Parse(dr["PostTime"].ToString())
                };
                return entity;
            }
            return null;
        }

    }

DAL类继承了DalBase,并实现了泛型接口。。
最后我们要完成Bll类:

public class AdminBll
    {
        private static readonly IOperate<AdminEntity> iDal = new AdminDal();
        public static bool UpdateData(AdminEntity entity)
        {
            return iDal.UpdateData(entity);
        }
        public static bool Delete(int Id)
        {
            return iDal.Delete(Id);
        }
        public static List<AdminEntity> GetList(string sqlStr)
        {
            return iDal.GetList(sqlStr);
        }
        public static DataTable GetTable(string where, string orderBy, int pageIndex, int pageSize, out int recordCount)
        {
            return iDal.GetTable(where, orderBy, pageIndex, pageSize, out recordCount);
        }
        public static AdminEntity GetDataById(int id)
        {
            return iDal.GetDataById(id);
        }

    }

那么,当我们需要调用方法的时候,代码是怎么样的?

var adminEntity = new AdminEntity()
            {
                UserName = "admin888",
                UserPwd = "admin888",
                Flag = "0",
                PostTime = DateTime.Now
            };
            AdminBll.UpdateData(adminEntity);

这样就实现了一个添加的操作。。。

其实我自己并不确定这样去使用泛型接口是否合理,欢迎大家喷,但请告诉我原因,因为我自认自己是菜鸟,需要学习。。。

时间: 2024-10-19 23:34:13

关于泛型接口的探讨的相关文章

Oracle12c多租户CDB 与 PDB 参数文件位置探讨、查询 CDB 与 PDB 不同值的参数

一. Oracle12c多租户CDB 与 PDB 参数文件位置 CDB的参数文件依然使用12c以前的SPIFLE,pdb的参数文件不会出现在SPFILE中,而是直接从CDB中继承,如果PDB中有privete Local parameter 会存在 CDB 的 PDB_SPFILE$字典表 中以con_id区别,当PDB UN-Plug时,PDB参数会写入PDB的XML文件中,当drop pluggable database后,pdb信息和PDB_SPFILE$记录也会被清除.再当PDB重新Pl

【算法整理】听说你写的算法很牛?-优质算法衡量标准探讨

引文 我有个朋友有算法强迫症,每次一看到别人写的算法,就有上去改的冲动,不然就会偏头疼,主要症结在于他认为别人写的算法不好,但是什么的算法可以评判为好,什么样的算法可以评判为不好?最近为了治愈他,我特地写了这篇文章. 算法的衡量从两个方向出发:时间复杂度和空间复杂度.本文主要是不讲具体算法,只将算法的衡量,重点讲解如何衡量算法的复杂度,解决平时见到的XX算法时间复杂是O(logn)O(logn),其中这个结果是怎么推导出来的?lognlogn是个什么玩意儿?,大写的OO是什么意思?为什么用这个符

面向数据可靠性存储系统设计思想探讨

存储系统的设计门槛是比较高的,和计算系统存在的最大区别在于存储系统所承载的是数据,一旦系统出现故障,不仅业务的连续性得不到保障,更为重要的是用户数据将会造成丢失.计算节点发生故障,最多造成业务连续性中断,这是与存储系统相比在可靠性要求方面最大的区别. 十几年前刚刚接触存储系统的研发,当时没有觉得存储有多复杂,不就是把数据按照一定规则存放在磁盘中,并且实现一定的功能,例如数据保护RAID.数据复制Replication.数据快照Snapshot以及文件系统嘛.感觉存储系统中最复杂的是各种功能,设计

泛型接口练习

泛型接口的说明高级应用

六爻预测等各种预测术的本质探讨之随机数猜想

对于各类预测术,比如六爻术,源于周易八卦.大家对预测术的观点泾渭分明,要么很相信,要么很不屑.或者有些人认为信则有不信则无. 当然我本人是信奉现代科学的,不过预测术确实有不可思议的地方,对过去和未来的分析不是简单的一句"巧合,概率论"能说的过去的.现经过本人的一番分析,试图对各类预测术的本质来个大起底. 其实,预测术不神奇,更不是有什么鬼神之力.而且也不能说古人比现在人更聪明.预测术的外圈是遵循一定规律的一整套规则,这些规则是古代在不停的经验总结中逐步完善的.换句话说,只要你自己能遵循

云存储技术优势及其发展趋势的探讨

云存储技术优势及其发展趋势的探讨 1.引言 近年来,由于信息技术的发展,科学计算和商业计算等众多应用领域会产生了规模相当巨大的数据,并且数据量仍在快速增加,呈海量形式发展.在科学计算方面,如物理学.天文学.生物学等领域都会产生规模庞大的数据,而且每年的数据规模达到若干PB.而在商业计算方面,Web搜索.社会网络等需要处理的数据规模也非常庞大,例如,Google和Facebook等应用产生的数据达到PB甚至EB级.按照摩尔定律,处理器的速度每18个月就会翻一番,光纤技术的发展也大大加快了数据在网络

集团信息化之路 电子采购软件与现有库存及财务软件数据对接的探讨

多个单体软件的应用,肯定就会涉及到不同软件直接数据对接的问题.这次计划应用的电子采购系统也同样遇到了这个问题,在这夜里与大家共同探讨一下系统间数据对接的问题. 由于历史原因,原有应用的财务系统采用了分布式部署,各系统直接完全独立,虽然每天个站点也将数据上传到总部,但是并未进行集中汇总处理.更要紧的是原来各系统的编码甚至都不统一各自为政,前几年还特意进行了一次编码统一工作,将编码进行统一.但是后续编码的添加维护工作也很难完全做到一致. 由于当前没有统一集中的数据编码,因此进行不同系统间的接口开发也

Android IOS WebRTC 音视频开发总结(七六)-- 探讨直播低延迟低流量的粉丝连麦技术

本文主要探讨基于WebRTC的P2P直播粉丝连麦技术 (作者:郝飞,亲加云CTO,编辑:dora),最早发表在[这里] 支持原创,转载必须注明出处,欢迎关注微信公众号blacker(微信ID:blackerteam  或 webrtcorgcn) 到目前为止,直播行业继续如预期的那样如火如荼的发展着,在先后竞争完延迟,高清,美 颜,秒开等功能后,最近各大直播平台比拼的一个热点就是连麦.什么是连麦? 简单??述 就是当主播直播期间,可以与其中某一个粉丝进行互动,并且其他粉丝能够观看到这个互动 过程

C++ 中左值和右值的探讨

我的主力博客:半亩方塘 对于 C++ 中的左值和右值,我们通常的说法是:当一个对象被用作右值的时候,用的是对象的值(内容):当对象被用作左值的时候,用的是对象的身份(在内存中的位置),这句话来自于 <C++ Primer 第五版> 第 121 页,那么,对于这句话,该作何理解呢?下面我想来谈谈我的看法: ISO C++03规定表达式必须是左值或右值之一,而在ISO C++11中,左值性被正式地扩充为更复杂的值类别,对于一个变量来说,与它相关的有两个部分:一是变量在内存中的地址,二是这个变量在内