.net 6及以上版本 普通控制台程序 初始化项目介绍(非WebAPI)

          最近做了一本地exe程序, 需要简单初始化一个.net core 10 的 Console 项目. 包括读取本地配置文件 appsettings.json,以及使用日志 啥的. 

本来最开始使用 Nlog作为日志记录的 ( 之前 ZR.Admin 里面 就是用的 Nlog ) ,结果项目开发完,说需要 对接 之前一个项目的   Elasticsearch(ES) ,头大,也不太方便调试ES,所以就抄原来的项目,直接使用原来项目的配置, 改为使用Log4Net了.

控制台Console项目 ,首先肯定是要记录日志, 读取配置文件啥的.然后操作数据库,使用SqlSugar,经典的三层模式(Model,DAL,BLL)调用就行了.

 

这里配置文件贴一下.

1.配置文件 Log4net.config 

Log4net.config连接ES日志
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<!-- This section contains the log4net configuration settings -->
	<log4net>
		<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
			<layout type="log4net.Layout.PatternLayout" value="%date [%thread] | %-5level | %message%newline" />
		</appender>

		<appender name="FileAppender" type="log4net.Appender.FileAppender">
			<file value="log-file.log" />
			<appendToFile value="true" />
			<layout type="log4net.Layout.PatternLayout">
				<conversionPattern value="%date [%thread] | %-5level| %message%newline" />
			</layout>
		</appender>

		<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
			<file value="logfile/" />
			<appendToFile value="true" />
			<rollingStyle value="Composite" />
			<staticLogFileName value="false" />
			<datePattern value="yyyyMMdd'.log'" />
			<maxSizeRollBackups value="10" />
			<maximumFileSize value="1MB" />
			<layout type="log4net.Layout.PatternLayout">
				<conversionPattern value="%date [%thread] | %-5level  | %message%newline" />
			</layout>
		</appender>
		<appender name="ElasticSearchAppender" type="log4net.ElasticSearchAppender.DotNetCore.ElasticSearchAppender, log4net.ElasticSearchAppender.DotNetCore">
			<Server>${"ES服务器地址:xxx.xxx.xxx.xxx"}</Server>
			<Port>9200</Port>
			<IndexName>${"ES服务器上搭建好的日志模块名称:xxxLog"}_%{+yyyy-MM-dd}</IndexName>
		</appender>
		<!-- Setup the root category, add the appenders and set the default level -->
		<root>
			<level value="ALL" />
			<appender-ref ref="ConsoleAppender" />
			<appender-ref ref="FileAppender" />
			<appender-ref ref="RollingLogFileAppender" />
			<!--<appender-ref ref="ElasticSearchAppender" /> -->
		</root>

	</log4net>
</configuration>

 

2.配置文件 appsettings.json 

简单的任务配置以及数据库配置
{
  "TaskConfig": {
      "MaxThreadCount": 50,
      "ThreadSleepTime": 5, 
      "GroupNum": 5     
  },
  "ConnectionStrings": {
       "conn_db_type": "3", // 数据库类型 SqlServer = 1,oracle =3,PostgreSQL=4
       "conn_db_main": "xxx";  // 数据库链接配置
  }
}

备注: 建议使用全局静态类 存储 配置项.  

 

3.通用日志类 Log4NetHelper.cs 

Log4NetHelper.cs 能用
using log4net;
using log4net.Config;
using log4net.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HelpCommon
{
    public class Log4NetHelper
    {

        private static string repositoryName = string.Empty;
        private static string logName = "xxxLog";
        private static log4net.ILog log = log4net.LogManager.GetLogger(logName);
        public static void Init()
        {
            ILoggerRepository repository = LogManager.CreateRepository("xxxLog");
            XmlConfigurator.Configure(repository, new FileInfo("Log4net.config"));
            repositoryName = repository.Name;
            log = LogManager.GetLogger(repository.Name, logName);
        }

      
        public static void ConsoleInfo(string msg)
        {
            Info(msg);
            Console.WriteLine(msg);
        }

        public static void Debug(string message)
        {

            log4net.ILog log = log4net.LogManager.GetLogger(logName);
            if (log.IsDebugEnabled)
            {
                log.Debug(message);
            }
            log = null;
        }

        public static void Debug(string message, Exception ex)
        {
           
            if (log.IsDebugEnabled)
            {
                log.Debug(message, ex);
            }
            
        }


        public static void Error(string message)
        {
          
            if (log.IsErrorEnabled)
            {
                log.Error(message);
            }
           
        }
        public static void Error(string message, Exception ex)
        {
          
            if (log.IsErrorEnabled)
            {
                log.Error(message, ex);
            }
           
        }

        public static void Fatal(string message)
        {

          
            if (log.IsFatalEnabled)
            {
                log.Fatal(message);
            }
          
        }
        public static void Fatal(string message, Exception ex)
        {

           
            if (log.IsFatalEnabled)
            {
                log.Fatal(message, ex);
            }
           
        }
        public static void Info(string message)
        {
            
            if (log.IsInfoEnabled)
            {
                log.Info(message);
            }
          
        }
        public static void Info(string message, Exception ex)
        {
          
            if (log.IsInfoEnabled)
            {
                log.Info(message, ex);
            }
          
        }
        public static void Warn(string message)
        {
           
            if (log.IsWarnEnabled)
            {
                log.Warn(message);
            }
           
        }
        public static void Warn(string message, Exception ex)
        {
          
            if (log.IsWarnEnabled)
            {
                log.Warn(message, ex);
            }
          
        }
    }
}

需要说明的是, 有时候记录日志(写文件),也要同时输出在控制台(方便观察).所以加了个 Log4NetHelper. ConsoleInfo 方法.

4.全局配置类  GlobalSetting.cs

GlobalSetting 全局配置类
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HelpCommon
{
    public static class GlobalSetting
    {
        private static IConfigurationRoot config = null;

        private static int _dbType;
        public static int DbType
        {
            get
            {
                return _dbType;
            }
        }

        private static string _dbConnStr;
        public static string DbConnStr
        {
            get
            {
                return _dbConnStr;
            }
        }

        public static DateTime LastDbTime { get; set; }
		
		public static void Init()
        {
            var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
            config = configuration.Build();

            // _maxCheckTime = GetSettingByInt("MaxCheckTime");
            // IChangeToken changeToken = config.GetReloadToken();

        }
		
		/// <summary>
        /// 初始化数据库配置
        /// </summary>
        public static void InitDB()
        {
            _dbConnStr = GetSetting("ConnectionStrings:conn_db_main");
            _dbType = GetSettingByInt("ConnectionStrings:conn_db_type");
        }

        /// <summary>
        /// 多个层级用英文:分割,例如: Logging:LogLevel:Default
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetSetting(string key)
        {
            try
            {
                var obj = config[key];
                if (!string.IsNullOrEmpty(obj))
                {
                    return obj;
                }
                return "";
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// 多个层级用英文:分割,例如: Logging:LogLevel:Default
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static int GetSettingByInt(string key)
        {
            var obj = config[key];
            if (int.TryParse(obj, out int p))
            {
                return p;
            }
            else
            {
                Console.WriteLine($"读取配置节[{key}]点错误");
                // 没有对应的值,返回-1
                return -1;
            }
        }
    }
}

 

5.程序Main方法初始化

Main方法入口 初始化日志,配置
static void Main(string[] args)
{          

	Log4NetHelper.Init();
	Log4NetHelper.ConsoleInfo("程序结束运行...");
	InitConfig();
	
	//这里写业务逻辑
	
	Log4NetHelper.ConsoleInfo("程序结束运行...");
	Console.WriteLine("程序终止运行");
	Console.ReadLine();
}


 static bool InitConfig()
 {
	try
	{
		Log4NetHelper.Info("加载配置文件并读取配置: ①数据库配置,②机器配置,③任务配置");
		 
		GlobalSetting.Init();
		GlobalSetting.InitDB();
		// GlobalSetting.InitTaskConfig(); 读取配置文件参数
			 
	 
		  // 检测一下数据库配置 
		 if (GlobalSetting.DbConnStr.indexOf("xxx.xxx.xxx.xxx") > 0)
		 {
			 Console.Write("注意:当前数据库连接为 ");

			 Console.BackgroundColor = ConsoleColor.White;
			 Console.ForegroundColor = ConsoleColor.Red;
			 Console.Write(" [测试库] xxx.xxx.xxx.xxx ");
			 Console.BackgroundColor = ConsoleColor.Black;
			 Console.ForegroundColor = ConsoleColor.White;
			 Console.WriteLine(" ,按回车继续...");
			 Console.ReadLine();
		 }
	 
		 Log4NetHelper.Info($"①数据库配置: 数据库类型:{GlobalSetting.DbType}");
		 //Log4NetHelper.Info($"②机器配置:" + JsonConvert.SerializeObject(GlobalSetting.MachineConfig));
		 //Log4NetHelper.Info($"③任务配置:" + JsonConvert.SerializeObject(GlobalSetting.TaskConfig));
			
		 // 更新数据库,注册配置 (回写到数据库)
		 //ConfigManagerBLL.SaveMachineConfig();
		 //ConfigManagerBLL.SaveTaskConfig();
			
			
		 // 检查数据库表里面配置的其他表或者参数, 如果没有配置, 需要提醒一下 

		 string sjcMsf = string.Empty; ;
		 var checkAllowRun = ConfigManagerBLL.CheckConfigStartTime(ref sjcMsf);

		while (!checkAllowRun)
		{
			Console.WriteLine("请检查 配置表 esb_task_config,设置 主机 取数的 开始时间戳和结束时间戳.....");
			Thread.Sleep(5000);
			checkAllowRun = ConfigManagerBLL.CheckConfigStartTime(ref sjcMsf);
		}
		Log4NetHelper.ConsoleInfo(sjcMsf);	
		return true;
	}
	catch (Exception ex)
	{
		 Log4NetHelper.Error("初始化读取appsettings.json配置异常", ex);
		 return false;
	}
}

 

5.解决方案项目结构

项目结构一目了然,经典的三层结构. HelpCommon 基本都是常用的类,不过多赘述.

需要说明的是 Lib目录 ,一般是放置 第三方DLL库之类的. 这里放几个文件说明,便于了解项目.(等时间一长,很多就都忘啦)

image

 

6.分页入参,出参通用类

EsbModel 下面有2个分页的实体类,一种是泛型的(返回值),另一个是分页入参(方法传参用)

泛型分页PagedInfo
    /// <summary>
    /// 分页参数
    /// </summary>
    public class PagedInfo<T>
    {
        /// <summary>
        /// 每页行数
        /// </summary>
        public int PageSize { get; set; } = 10;
        /// <summary>
        /// 当前页
        /// </summary>
        public int PageIndex { get; set; } = 1;
        /// <summary>
        /// 总记录数
        /// </summary>
        public int TotalNum { get; set; }
        /// <summary>
        /// 总页数
        /// </summary>
        public int TotalPage
        {
            get
            {
                if (TotalNum > 0)
                {
                    return TotalNum % this.PageSize == 0 ? TotalNum / this.PageSize : TotalNum / this.PageSize + 1;
                }
                else
                {
                    return 0;
                }
            }
            set { }
        }
        public List<T> Result { get; set; }
        public Dictionary<string, object> Extra { get; set; } = new Dictionary<string, object>();
        public PagedInfo()
        {
        }
    }

 

分页方法入参传参 PagerInfo
public class PagerInfo
{
    /// <summary>
    /// 当前页码
    /// </summary>
    public int PageNum { get; set; }
    public int PageSize { get; set; }
    /// <summary>
    /// 总记录数
    /// </summary>
    public int TotalNum { get; set; }
    /// <summary>
    /// 总页码
    /// </summary>
    /// <summary>
    /// 总页数
    /// </summary>
    public int TotalPage
    {
        get
        {
            return TotalNum > 0 ? TotalNum % PageSize == 0 ? TotalNum / PageSize : TotalNum / PageSize + 1 : 0;
        }
    }

    /// <summary>
    /// 排序字段
    /// </summary>
    public string Sort { get; set; } = string.Empty;
    /// <summary>
    /// 排序类型,前端传入的是"ascending","descending"
    /// </summary>
    public string SortType { get; set; } = string.Empty;
    public PagerInfo()
    {
        PageNum = 1;
        PageSize = 20;
    }

    public PagerInfo(int page = 1, int pageSize = 20)
    {
        PageNum = page;
        PageSize = pageSize;
    }
}

 

7. 数据库操作 SqlSugarHelper

SqlSugarHelper 数据库操作

using SqlSugar;
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using System.Collections;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;

namespace HelpCommon
{
    public static class SqlSugarHelper
    {
        public static string _connStr;
        public static string connStr
        {
            get
            {
                if (string.IsNullOrEmpty(_connStr))
                {
                    _connStr = GlobalSetting.DbConnStr;
                }
                return _connStr;
            }
        }



        public static SqlSugarScope _db = null;
        public static SqlSugarScope db
        {
            get
            {
                if (_db == null)
                {
                    _db = new SqlSugarScope(new SqlSugar.ConnectionConfig()
                    {
                        ConnectionString = connStr,
                        DbType = SqlSugar.DbType.Oracle,
                        IsAutoCloseConnection = true,
                        // 需要查看运行时的sql,打开下面的注释
                        //AopEvents = new AopEvents
                        //{
                        //    OnLogExecuting = (sql, p) =>
                        //    {
                        //        Parallel.For(0, 1, e =>
                        //        {
                        //            string sqlStr = GetParas(p) + "【SQL语句】:" + sql;
                        //            Console.ForegroundColor = ConsoleColor.Green;
                        //            Console.WriteLine(sqlStr);
                        //            Console.ForegroundColor = ConsoleColor.White;
                        //        });
                        //    }
                        //},
                    }); ;
                }
                return _db;
            }
        }

        private static string GetParas(SugarParameter[] pars)
        {
            string key = "【SQL参数】:";
            foreach (var param in pars)
            {
                key += $"{param.ParameterName}:{param.Value}\n";
            }
            return key;
        }

        /*
          批量新增/修改 使用: db.Storageable<T>(List<T>list).ExecuteCommand();
          sql->List<T> 使用:  db.Ado.SqlQuery<T>(sql, parms);
         */

        public static DataTable GetDataTable(string sql, object parms = null)
        {

            return db.Ado.GetDataTable(sql, parms);
        }
        public static int ExecuteNonQuery(string sql, object parms = null)
        {
            return db.Ado.ExecuteCommand(sql, parms);
        }
        public static object GetScalar(string sql, object parms = null)
        {
            return db.Ado.GetScalar(sql, parms);
        }

        public static DateTime GetDbTime()
        {
            return Convert.ToDateTime(db.Ado.GetScalar("select sysdate from dual"));
        }
        public static DateTime GetDbTimeStemp()
        {
            var obj = db.Ado.GetScalar("select to_char(SYSTIMESTAMP,'YYYY-MM-DD HH24:MI:SS.ff6') from dual");
            return TimeHelper.StrToSjc(obj.ToString());
        }
    }
}

 

需要说明的是  批量保存 和  实体类查询 方法 

 批量新增/修改  使用:  db.Storageable<T>(List<T>list).ExecuteCommand();
 sql -> List<T> 使用:  db.Ado.SqlQuery<T>(sql, parms);

 

posted @ 2025-12-20 17:33  兴想事成  阅读(2)  评论(0)    收藏  举报