iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >C#抽象增删改怎么实现
  • 724
分享到

C#抽象增删改怎么实现

2023-06-17 07:06:03 724人浏览 安东尼
摘要

本篇内容主要讲解“C#抽象增删改怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#抽象增删改怎么实现”吧!现在业界火了一种ORM 框架,那就是Dapper,我也是Dapper的粉丝之一,

本篇内容主要讲解“C#抽象增删改怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#抽象增删改怎么实现”吧!

现在业界火了一种ORM 框架,那就是Dapper,我也是Dapper的粉丝之一,而我总结出来的框架也是基于Daaper。下面是我的代码,首先是Dapper Helper类,数据库通用访问类(用Nuget工具先把Dapper类引用到NetUtility.Dapper.Core项目中去):

NetUtility.Dapper.Core.DataBaseAccess.cs

  1. using System; 

  2. using System.Collections.Generic; 

  3. using System.Configuration; 

  4. using System.Data.sqlClient; 

  5. using System.Linq; 

  6. using System.Text; 

  7. using System.Threading.Tasks; 

  8. using Dapper; 

  9. using System.Data; 

  10. using NetUtility.Entity; 

  11. using System.Reflection; 

  12.  

  13. namespace NetUtility.Dapper.Core 

  14.     /// <summary> 

  15.     /// 数据库访问类 

  16.     /// </summary> 

  17.     public class DataBaseAccess 

  18.     { 

  19.         public static SqlConnection CreateConnection() 

  20.         { 

  21.             string connStr = ConfigurationManager.ConnectionStrings["connString"].ConnectionString; 

  22.             SqlConnection conn = new SqlConnection(connStr); 

  23.             conn.Open(); 

  24.             return conn; 

  25.         } 

  26.  

  27.         /// <summary> 

  28.         /// 执行增、删、改方法 

  29.         /// </summary> 

  30.         /// <param name="sql"></param> 

  31.         /// <param name="parms"></param> 

  32.         /// <returns></returns> 

  33.         public static int Execute(string sql, object parms = null) 

  34.         { 

  35.             using (IDbConnection conn = CreateConnection()) 

  36.             { 

  37.                 return conn.Execute(sql,parms); 

  38.             } 

  39.         } 

  40.  

  41.         /// <summary> 

  42.         /// 得到单行单列 

  43.         /// </summary> 

  44.         /// <param name="sql"></param> 

  45.         /// <param name="parms"></param> 

  46.         /// <returns></returns> 

  47.         public static object ExecuteScalar(string sql, object parms = null) 

  48.         { 

  49.             using (IDbConnection conn = CreateConnection()) 

  50.             { 

  51.                 return conn.ExecuteScalar(sql, parms); 

  52.             } 

  53.         } 

  54.  

  55.         /// <summary> 

  56.         /// 单个数据集查询 

  57.         /// </summary> 

  58.         /// <param name="sql"></param> 

  59.         /// <param name="parms"></param> 

  60.         /// <returns></returns> 

  61.         public static List<TEntity> Query<TEntity>(string sql,Func<TEntity,bool> pre ,object parms = null) 

  62.         { 

  63.             using (IDbConnection conn = CreateConnection()) 

  64.             { 

  65.                 return conn.Query<TEntity>(sql, parms).Where(pre).ToList(); 

  66.             } 

  67.         } 

  68.  

  69.         /// <summary> 

  70.         /// 单个数据集查询 

  71.         /// </summary> 

  72.         /// <param name="sql"></param> 

  73.         /// <param name="parms"></param> 

  74.         /// <returns></returns> 

  75.         public static List<TEntity> Query<TEntity>(string sql, object parms = null) 

  76.         { 

  77.             using (IDbConnection conn = CreateConnection()) 

  78.             { 

  79.                 return conn.Query<TEntity>(sql, parms).ToList(); 

  80.             } 

  81.         }    

  82.  

  83.         /// <summary> 

  84.         /// 多个数据集查询 

  85.         /// </summary> 

  86.         /// <param name="sql"></param> 

  87.         /// <param name="parms"></param> 

  88.         /// <returns></returns> 

  89.         public static SqlMapper.GridReader MultyQuery(string sql, object parms = null) 

  90.         { 

  91.             using (IDbConnection conn = CreateConnection()) 

  92.             { 

  93.                 return  conn.QueryMultiple(sql, parms); 

  94.             } 

  95.         } 

  96.  

  97.         /// <summary> 

  98.         /// 单个数据集查询 

  99.         /// </summary> 

  100.         /// <param name="sql"></param> 

  101.         /// <param name="parms"></param> 

  102.         /// <returns></returns> 

  103.         public static TEntity FirstOrDefault<TEntity>(string sql,Func<TEntity,bool> selector, object parms = null) 

  104.         { 

  105.             using (IDbConnection conn = CreateConnection()) 

  106.             { 

  107.                 return conn.Query<TEntity>(sql, parms).Where(selector).FirstOrDefault(); 

  108.             } 

  109.         } 

  110.     } 

  111. }

我把增删改查抽象出来了,少不了的就是SQL语句的生成,生成SQL语句,要么是映射,要么是反射,而我用的是反射,给一个Entity类,我读取他所有属性和字段,然后生成对应的SQL语句。 NetUtility.Dapper.Core.DataMapping.cs

using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks;  namespace NetUtility.Dapper.Core {     internal class DataMapping<TModel> where TModel : class     {         #region 数据库类型+DataBaseType         /// <summary>         /// 数据库类型         /// </summary>         public static string DataBaseType         {             get             {                 string strType = ConfigurationManager.AppSettings["DataBaseType"];                 if (!string.IsNullOrEmpty(strType))                 {                     return strType;                 }                 else                 {                     return string.Empty;                 }             }         }          #endregion          #region 主键属性字段+PrimaryKey         /// <summary>         /// 主键字段名称         /// </summary>         public static string PrimaryKey         {             get             {                 Type t = typeof(TModel);                 TableInfoAttribute tableInfo = t.GetCustomAttribute(typeof(TableInfoAttribute), true) as TableInfoAttribute;                    if (tableInfo!=null)//如果没有标识表信息特性,则通过表名向数据库中得到主键信息                 {                     return tableInfo.PrimaryKey;                               }                 else                 {                     string tableName = TableName();                     return DataBaseAccess.ExecuteScalar("SELECT name FROM SysColumns WHERE id=Object_Id('" + tableName + "') and colid=(select top 1 colid from sysindexkeys where id=Object_Id('" + tableName + "'))").ToString();                 }             }         }          #endregion          #region 获取表名+TableName         /// <summary>         /// 获取表名         /// </summary>         /// <param name="prev">数据库表名前缀</param>         /// <returns></returns>         public static string TableName(string prev = "")         {             Type t = typeof(TModel);             TableInfoAttribute tableInfo = t.GetCustomAttribute(typeof(TableInfoAttribute), true) as TableInfoAttribute;             return tableInfo != null ? tableInfo.TableName : string.Concat(prev, t.Name);         }          #endregion          #region Select 查询语句+GetQuerySql         /// <summary>         /// Select 查询语句         /// </summary>         /// <returns></returns>         public static string GetQuerySql()         {             StringBuilder sql = new StringBuilder("select * from ");             sql.Append(TableName());              return sql.ToString();         }          #endregion          #region Insert非Null属性的对象实例 Sql 语句+GetInsertSql         /// <summary>         /// Insert 非Null属性的对象实例 Sql 语句         /// </summary>         /// <param name="model"></param>         /// <returns></returns>         public static string GetInsertSql(TModel model)         {             StringBuilder sql = new StringBuilder("insert into ");              string[] props = Propertys(model);             sql.Append(TableName());             sql.Append("(");             sql.Append(string.Join(",", props));             sql.Append(") values(@");             sql.Append(string.Join(",@", props));             sql.Append(");select @@IDENTITY");              return sql.ToString();         }          #endregion          #region Delete Sql 语句+GetDeleteSql         /// <summary>         /// Delete Sql 语句         /// </summary>         /// <returns></returns>         public static string GetDeleteSql()         {             return string.Format(@"delete from {0} where {1} in @IdList", TableName(), PrimaryKey);         }          #endregion          #region Update 非Null属性的对象实例 Sql语句+GetUpdateSql         /// <summary>         /// Update 非Null属性的对象实例 Sql语句         /// </summary>         /// <param name="model"></param>         /// <returns></returns>         public static string GetUpdateSql(TModel model)         {             StringBuilder sql = new StringBuilder("update ");             string[] props = Propertys(model);             sql.Append(TableName());             sql.Append(" set ");             foreach (string propName in props)             {                 sql.Append(propName + "=@" + propName + ",");             }             sql.Remove(sql.Length - 1, 1);             sql.Append(" where " + PrimaryKey + "=@Id");             return sql.ToString();         }          #endregion          #region 非主键且非Null属性集合+Propertys         /// <summary>         /// 非主键且非Null属性         /// </summary>         /// <param name="model"></param>         /// <returns></returns>         public static string[] Propertys(TModel model)         {             PropertyInfo[] props = typeof(TModel).GetProperties();             List<string> list = new List<string>();             string key = PrimaryKey;             if (props != null && props.Length > 0)             {                 foreach (PropertyInfo prop in props)                 {                     if (prop.GetValue(model, null) != null && !prop.Name.Equals(key, StrinGComparison.OrdinalIgnoreCase))                     {                         list.Add(prop.Name);                     }                 }             }              return list.ToArray();         }          #endregion     } }

代码中的TableInfoAttribute 类是我建一个属性特性类,用于标识表名和主键名称的特性类,假如Entity实体类上面没有标识主键名称,框架默认会用Entity类名作为表名,建议***标识一下表名和主键名称。

NetUtility.Dapper.Core.TableInfoAttribute.cs

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;  namespace NetUtility.Dapper.Core {     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true, Inherited = true)]     /// <summary>     /// 标识表名、主键等信息特性类     /// </summary>     public class TableInfoAttribute : Attribute     {         /// <summary>         /// 数据库表名         /// </summary>         public string TableName { get; set; }          /// <summary>         /// 主键名称         /// </summary>         public string PrimaryKey { get; set; }          public TableInfoAttribute()         { }         public TableInfoAttribute(string tableName, string key)         {             this.TableName = tableName;             this.PrimaryKey = key;         }     } }using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;  namespace NetUtility.Dapper.Core {     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true, Inherited = true)]     /// <summary>     /// 标识表名、主键等信息特性类     /// </summary>     public class TableInfoAttribute : Attribute     {         /// <summary>         /// 数据库表名         /// </summary>         public string TableName { get; set; }          /// <summary>         /// 主键名称         /// </summary>         public string PrimaryKey { get; set; }          public TableInfoAttribute()         { }         public TableInfoAttribute(string tableName, string key)         {             this.TableName = tableName;             this.PrimaryKey = key;         }     } }

好,下面就是新建一个抽象类,用于抽象出增删改查的 ExecuteSql<TModel> 泛型抽象类

NetUtility.Dapper.Core.ExecuteSql.cs

using Dapper; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;  namespace NetUtility.Dapper.Core {     public abstract class ExecuteSql<TModel> where TModel : class     {         #region Insert非Null属性的对象实例+Insert(TModel model)         /// <summary>         /// Insert非Null属性的对象实例         /// </summary>         /// <param name="model"></param>         /// <returns></returns>         public virtual int Insert(TModel model)         {             string sql = DataMapping<TModel>.GetInsertSql(model);             object res = DataBaseAccess.ExecuteScalar(sql, model);             if (res != null)             {                 return Convert.ToInt32(res);             }             return 0;         }          #endregion          #region Select * 查询+Query()         /// <summary>         /// Select * 查询         /// </summary>             /// <returns></returns>         public virtual List<TModel> Query()         {             string sql = DataMapping<TModel>.GetQuerySql();             return DataBaseAccess.Query<TModel>(sql);         }          #endregion          #region 带查询条件的Select查询+Query(Func<TModel, bool> selector)         /// <summary>         /// 带查询条件的Select查询         /// </summary>         /// <param name="selector"></param>         /// <returns></returns>         public virtual List<TModel> Query(Func<TModel, bool> selector)         {             string sql = DataMapping<TModel>.GetQuerySql();             return DataBaseAccess.Query<TModel>(sql, selector);         }          #endregion          #region  得到一个对象的实例+FirstOrDefault(Func<TModel, bool> selector = null)         /// <summary>         /// 得到一个对象的实例         /// </summary>         /// <param name="selector"></param>         /// <returns></returns>         public virtual TModel FirstOrDefault(Func<TModel, bool> selector = null)         {             string sql = DataMapping<TModel>.GetQuerySql();             return DataBaseAccess.FirstOrDefault<TModel>(sql, selector);         }          #endregion          #region 批量删除+Delete(string[] IdList)         /// <summary>         /// 批量删除         /// </summary>         /// <param name="IdList"></param>         /// <returns></returns>         public virtual int Delete(string[] IdList)         {             return DataBaseAccess.Execute(DataMapping<TModel>.GetDeleteSql(), new { IdList = IdList });         }          #endregion          #region Update 一个非Null属性的对象+Update(TModel model)         /// <summary>         /// Update 一个非Null属性的对象         /// </summary>         /// <param name="model"></param>         /// <returns></returns>         public virtual int Update(TModel model)         {             return DataBaseAccess.Execute(DataMapping<TModel>.GetUpdateSql(model), model);         }          #endregion          #region 获取多个数据集+MultyQuery(string sql, object param = null)         /// <summary>         /// 获取多个数据集         /// </summary>         /// <param name="sql"></param>         /// <param name="param"></param>         /// <returns></returns>         public virtual SqlMapper.GridReader MultyQuery(string sql, object param = null)         {             return DataBaseAccess.MultyQuery(sql, param);         }          #endregion              } }

ExecuteSql.cs 类中的方法全是  virsual方法,使用者可以重写他,特别是查询方法,一定会被重写掉。现在NetUtility.Dapper.Core项目中的类全部写完了,现在 是我业务类的引用了,我现在只需要建一个业务类继承这个抽象类,这些增删改查方法全都有了,已经不需要写了!

下面是我的两个实体类,实体类用TableInfoAttribute特性类标识出了主键名称和表名称:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NetUtility.Dapper.Core;  namespace NetUtility.Entity {     [TableInfo(PrimaryKey ="Id",TableName ="Classes")]     public class Classes     {   public int Id { get; set; }         public string Name { get; set; }         public string Code { get; set; }     } }  using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NetUtility.Dapper.Core;  namespace NetUtility.Entity {     [TableInfo(PrimaryKey = "Id", TableName = "Student")]     public class Student     {                public int Id { get; set; }         public string Name { get; set; }         public string Code { get; set; }         public int? Age { get; set; }         public DateTime? JoinDate { get; set; }         public int? ClassesId { get; set; }     } }

我再新建一个StudentRepertories业务类,继承ExecuteSql抽象类。

NetUtility.Repertories.StudentRepertories.cs

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NetUtility.Dapper.Core; using NetUtility.Entity; using NetUtility.Entity.ExstendEntity;//这个是实体类的扩展类,项目中如不需要可移除 using System.Data; using Dapper;  namespace NetUtility.Repertories {     public class StudentRepertories : ExecuteSql<Student>     {          public override List<Student> Query()         {             return base.Query();         }          public  List<StudentInfo> QueryInfo()         {             string sql = "select * from Student a left join Classes b on a.ClassesId=b.Id";              using (IDbConnection conn = DataBaseAccess.CreateConnection())             {                 return conn.Query<StudentInfo, Classes, StudentInfo>(sql, (stu, classes) => { stu.ClassesModel = classes; return stu; }).ToList();                }         }     } }

好了,现在我们只需要建一个控制台测试一下有没有问题就是了,亲测,木有问题。

NetUtility.ConsoleItem

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using NetUtility.Repertories; using NetUtility.Entity;  namespace NetUtility.ConsoleItem {     class Program     {         static void Main(string[] args)         {             //业务对象              StudentRepertories stu = new StudentRepertories();             //实体对象             var model = new Student(){Age = 100,ClassesId = 1,Code = "3200020021",JoinDate = DateTime.Now,Name = "老徐"};                    //新增一个对象             int StudentId = stu.Insert(model);             var newModel = stu.FirstOrDefault(a => a.Id == StudentId);              //Lambda表达式查询             var list = stu.Query(a => a.Age == 100);             //不带参数查询             var studentInfoList = stu.QueryInfo();              #region 更新             newModel.Code = "1111111111";             newModel.Id = StudentId;             stu.Update(newModel);             #endregion           // 删除             stu.Delete(new string[] { newModel.Id.ToString() });                      Console.ReadKey();         }     } }

到此,相信大家对“C#抽象增删改怎么实现”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: C#抽象增删改怎么实现

本文链接: https://www.lsjlt.com/news/287574.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C#抽象增删改怎么实现
    本篇内容主要讲解“C#抽象增删改怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#抽象增删改怎么实现”吧!现在业界火了一种ORM 框架,那就是Dapper,我也是Dapper的粉丝之一,...
    99+
    2023-06-17
  • javascript对象的增删改查怎么实现
    小编给大家分享一下javascript对象的增删改查怎么实现,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!什么是对象?嘿!这还用问吗?对象不就是“你的女朋友” 嘛!,或许你以为我在胡说,但事实上确实就是。看完下面这个定义,...
    99+
    2023-06-29
  • mybatis抽取基类BaseMapper增删改查的实现
    目录准备工作:1:数据库表2:准备实体类步骤1:编写工具类Tools:作用:用于驼峰和数据库字段的转换步骤2:自定义两个注解,分别用于类字段的排除和字义主键步骤3:自定义动态sql生...
    99+
    2022-11-12
  • C++_String增删查改模拟实现
    C++_String增删查改模拟实现 前言一、string默认构造、析构函数、拷贝构造、赋值重载1.1 默认构造1.2 析构函数1.3 拷贝构造1.4 赋值重载 二、迭代器和范围for三、元素相关:operator[ ]四、容量...
    99+
    2023-12-23
    c++ java jvm c语言 笔记 stl
  • MongoDB怎么实现增删改查
    这篇“MongoDB怎么实现增删改查”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“MongoDB怎么实现增删改查”文章吧。一...
    99+
    2023-06-30
  • C#实现学生模块的增删改查
    本文实例为大家分享了C#实现学生模块的增删改查的具体代码,供大家参考,具体内容如下 using System; using System.Collections.Generic; ...
    99+
    2022-11-13
  • PHP怎么实现增删改查功能
    这篇文章主要讲解了“PHP怎么实现增删改查功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PHP怎么实现增删改查功能”吧!sql:-- phpMyAdmin SQL&n...
    99+
    2023-06-29
  • winform增删改查功能怎么实现
    在 Winform 中实现增删改查功能,可以按照以下步骤进行操作:1. 设计界面:在 Winform 窗体上添加相应的控件,如文本框...
    99+
    2023-09-13
    winform
  • 怎么用eclipse实现Java增删查改
    要使用Eclipse实现Java的增删查改操作,你可以按照以下步骤进行:1. 创建一个Java项目:打开Eclipse,选择File...
    99+
    2023-08-14
    eclipse Java
  • C#操作SQLite实现数据的增删改查
    目录简介主要代码SQLiteHelper.csUsingLock.csForm1.cs简介 SQLite是一个轻量级、跨平台的关系型数据库,在小型项目中,方便,易用,同时支持多种开发...
    99+
    2022-11-13
  • 怎么实现JavaWeb用户的增删改查
    本篇内容介绍了“怎么实现JavaWeb用户的增删改查”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!准备工作后端技术前端技术角色维护-分页实现...
    99+
    2023-06-16
  • MongoDB增删改查之查询怎么实现
    这篇文章主要介绍MongoDB增删改查之查询怎么实现,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!详述1.简单查询:>db.t1.find() { "_id...
    99+
    2022-10-18
  • mongodb中怎么实现增删改查操作
    这篇文章给大家介绍mongodb中怎么实现增删改查操作,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。一: Insert操作上一篇也说过,文档是采用“K-V”格式存储的,如果大...
    99+
    2022-10-18
  • vue中怎么实现增删改查操作
    vue中怎么实现增删改查操作,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。具体内容如下我们把这些用户信息保存到list的数组中,然后增删改查就...
    99+
    2022-10-19
  • python字典的增删改查怎么实现
    在Python中,字典的增删改查可以通过以下方式实现:1. 增加字典项:- 使用键值对的形式直接赋值:`dict[key] = va...
    99+
    2023-10-11
    python
  • java怎么实现数组的增删改查
    本篇内容主要讲解“java怎么实现数组的增删改查”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java怎么实现数组的增删改查”吧!目录一维数组数组的扩容数组的复制直接将数组赋值给新数组创建一个新...
    99+
    2023-06-20
  • winform数据库增删改查怎么实现
    在WinForm应用程序中实现对数据库的增删改查操作,可以按照以下步骤进行:1. 创建数据库连接:使用合适的数据库连接对象(如Sql...
    99+
    2023-09-05
    winform 数据库
  • SpringBoot怎么整合Mongodb实现增删查改
    今天小编给大家分享一下SpringBoot怎么整合Mongodb实现增删查改的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一...
    99+
    2023-06-30
  • Django开发RESTful API怎么实现增删改查
    小编给大家分享一下Django开发RESTful API怎么实现增删改查,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!数据库中有user表如下:新建一个Djang...
    99+
    2023-06-15
  • 使用PyMySQL怎么实现增删查改操作
    使用PyMySQL怎么实现增删查改操作?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1、PyMySQL的使用步骤:2、案例:1 查询数据库中的表的信息: #&nb...
    99+
    2023-06-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作