十年河东,十年河西,莫欺少年穷
学无止境,精益求精
每次搭建NetCore控制台应用程序都得费个十几分钟时间,甚至更多
索性搞个简易版的,供以后复用
1、新建Net6控制台应用程序
1.1、项目文件
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.6" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" /> <PackageReference Include="NLog.Extensions.Logging" Version="5.0.4" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\CoreDbContext\CoreDbContext.csproj" /> <ProjectReference Include="..\swapCommon\swapCommon.csproj" /> <ProjectReference Include="..\swapModels\swapModels.csproj" /> </ItemGroup> <ItemGroup> <None Update="appsettings.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> <None Update="nlog.config"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup> </Project>
项目文件中引入的包,可以原封不动直接复制到你的项目文件中
该控制台项目引用了三个外部项目,关于这三个外部项目最后说明
项目中创建了两个配置文件,appsettings.json 和 nlog.config ,分别属于系统配置文件和Nlog日志配置文件
内容分别如下:
appsettings.json 属性需要设置为始终复制
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "virtualPath": "", //调试时为空,swap环境:/dev/swap 正式环境:/swap "ConnectionStrings": { "swapDbContext": "Data Source=10.11.12.13;Initial Catalog=swap;Password=xxx;User ID=sa;" }, "MongoDatabaseName": "swapApiLogsDb", "MongoDbConnect": "mongodb://127.0.0.1:27017", "RedisConnectionString": "127.0.0.1:6379,allowadmin=true", "RedisDbNum": 0, "IotRedisDbNum": 1, "UploadFileOptions": { "FileTypes": ".gif,.jpg,.jpeg,.png,.bmp,.GIF,.JPG,.JPEG,.PNG,.BMP,.xls,.xlsx", "MaxSize": 104857600, "BaseUrl": "D:\\dotnet\\fileServer\\WuanManagerFiles", "BasePath": "Uploads", "ServerUrl": "https://portal.one5a.com/Uploads" } }View Code
nlog.config 属性需要设置为始终复制
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="Info" internalLogFile="internal-nlog-AspNetCore.txt"> <!-- enable asp.net core layout renderers --> <extensions> <add assembly="NLog.Web.AspNetCore"/> </extensions> <!-- the targets to write to --> <targets> <!-- File Target for all log messages with basic details --> <target xsi:type="File" name="allfile" fileName="logs/log-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" archiveAboveSize="10000" maxArchiveFiles="3"/> <!-- File Target for own log messages with extra web details using some ASP.NET core renderers --> <target xsi:type="File" name="ownFile-web" fileName="nlog-AspNetCore-own-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}" archiveAboveSize="10000" maxArchiveFiles="3" /> <!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection --> <target xsi:type="Console" name="lifetimeConsole" layout="${MicrosoftConsoleLayout}" /> </targets> <!-- rules to map from logger name to target --> <rules> <!--All logs, including from Microsoft--> <logger name="*" minlevel="Trace" writeTo="allfile" /> <!--Output hosting lifetime messages to console target for faster startup detection --> <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="lifetimeConsole, ownFile-web" final="true" /> <!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) --> <logger name="Microsoft.*" maxlevel="Info" final="true" /> <logger name="System.Net.Http.*" maxlevel="Info" final="true" /> <logger name="*" minlevel="Trace" writeTo="ownFile-web" /> </rules> </nlog>View Code
2、Program 代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using CoreDbContext; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using NLog.Extensions.Logging; using swapModels; namespace CabinetService { static class Program { static void Main() { ConfigurationBuilder builder = new ConfigurationBuilder(); builder.AddJsonFile("appsettings.json", true, true); var ConfigRoot = builder.Build();//根节点 ServiceCollection Services = new ServiceCollection(); Services.AddDbContext<swapDbContext>(options => options.UseSqlServer(ConfigRoot.GetConnectionString("swapDbContext")), ServiceLifetime.Scoped); // Services.AddLogging(log => { log.AddConsole(); log.AddNLog(); log.SetMinimumLevel(LogLevel.Information); }); Services.AddScoped<LogService>(); Services.AddScoped<DbTest>(); Services.AddScoped<coreOptions>(); Services.AddOptions().Configure<UploadFileOptions>(A => ConfigRoot.GetSection("UploadFileOptions").Bind(A)); // using (ServiceProvider provider = Services.BuildServiceProvider()) { //测试数据库 var dbTest = provider.GetService<DbTest>(); dbTest.Test(); //选项模式测试 var options= provider.GetService<coreOptions>(); options.Test(); //测试日志 var logservice = provider.GetService<LogService>(); logservice.test(); } } } /// <summary> /// efCore first 测试 /// </summary> public class DbTest { private readonly swapDbContext context; public DbTest(swapDbContext context) { this.context = context; } public void Test() { var linq = context.Users.Where(A => A.uid != ""); var sql = linq.ToQueryString(); Console.WriteLine("linq转化为的SQL语句为:" + sql); var data = linq.ToList(); foreach (var item in data) { Console.WriteLine(item.userName); } } } public class coreOptions { private readonly IOptionsSnapshot<UploadFileOptions> options; public coreOptions(IOptionsSnapshot<UploadFileOptions> options) { this.options = options; } public void Test() { Console.WriteLine("========================================"); Console.WriteLine(options.Value.BaseUrl); Console.WriteLine(options.Value.MaxSize); Console.WriteLine(options.Value.FileTypes); } } public class LogService { private readonly ILogger<LogService> logger; public LogService(ILogger<LogService> logger) { this.logger = logger; } public void test() { for (int i = 0; i < 10; i++) { logger.LogTrace("跟踪"); logger.LogDebug("调试"); logger.LogInformation("信息"); logger.LogError("错误"); logger.LogCritical("严重错误"); try { int a = 0; int b = 1; var c = b / a; } catch (Exception ex) { logger.LogError(ex, "异常"); } } } /// <summary> /// windows 日志 部署在linux 下无效 /// </summary> public void EventLog() { //Microsoft.Extensions.Logging.EventLog } } }View Code
2.1、选项模式中用到 swapModels 中定义的实体类,如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class UploadFileOptions { /// <summary> /// 允许的文件类型 /// </summary> public string FileTypes { get; set; } /// <summary> /// 最大文件大小 /// </summary> public int MaxSize { get; set; } /// <summary> /// 文件的基地址 /// </summary> public string BaseUrl { get; set; } /// <summary> /// IIS 虚拟路径 解析到 BaseUrl /// </summary> public string BasePath { get; set; } public string ServerUrl { get; set; } }View Code
2.2、DbContext 数据库上下文
根据项目文件可知,该控制台应用程序引用项目CoreDbContext ,CoreDbContext 采用EFCORE+DbFirst的模式进行搭建,下面简单贴出部分代码
swapDbContext
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using CoreDbContext.DbDtos; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; namespace CoreDbContext { /// <summary> /// add-Migration -Context 可以通过-Context 指定上下文,因此,项目中可以有多个DbCOntext,这样就支持多个数据库 /// </summary> public class swapDbContext : DbContext { public DbSet<T_Group> Groups { get; set; } public DbSet<T_AppInfo> AppInfos { get; set; } public DbSet<T_User> Users { get; set; } public DbSet<T_Role> Roles { get; set; } public DbSet<T_UserRole> UserRoles { get; set; } public DbSet<T_Station> Stations { get; set; } public DbSet<T_SysDictionary> SysDictionaries { get; set; } public DbSet<T_CabinetProduce> CabinetProduces { get; set; } public DbSet<T_Cabinet> Cabinets { get; set; } public DbSet<T_BatteryProduce> BatteryProduces { get; set; } public DbSet<T_Battery> Batteries { get; set; } public DbSet<C_Customer> Customers { get; set; } public DbSet<C_CustomerBattery> CustomerBatteries { get; set; } public DbSet<C_ChargeGoods> ChargeGoods { get; set; } public DbSet<C_ChargeGoodOrder> ChargeGoodOrders { get; set; } public DbSet<C_ChargeGoodOrderDtl> ChargeGoodOrderDtls { get; set; } public DbSet<C_Deposit> Deposits { get; set; } public DbSet<C_DepositOrder> DepositOrders { get; set; } public DbSet<C_DepositApply> DepositApplies { get; set; } public DbSet<T_Document> Documents { get; set; } public DbSet<T_SysParam> SysParams { get; set; } public swapDbContext() : base() { } public swapDbContext(DbContextOptions<swapDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { //关闭级联删除 var foreignKeys = modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()).Where(fk => fk.DeleteBehavior == DeleteBehavior.Cascade); foreach (var fk in foreignKeys) { fk.DeleteBehavior = DeleteBehavior.Restrict; } //建立索引 并 增加唯一性约束 modelBuilder.Entity<T_CabinetProduce>().HasIndex(u => u.batchNo).IsUnique(); base.OnModelCreating(modelBuilder); //从当前程序集命名空间加载所有的IEntityTypeConfiguration modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly); } } /// <summary> /// 开发环境专用 用于add-Migration 时使用 /// </summary> public class swapDbContextFactory : IDesignTimeDbContextFactory<swapDbContext> { public swapDbContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder<swapDbContext>(); optionsBuilder.UseSqlServer("Data Source=1.2.3.4;Initial Catalog=swap;Password=xxx;User ID=sa;"); return new swapDbContext(optionsBuilder.Options); } } }View Code
dto_User
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/// <summary> /// 用于平台登录 /// </summary> public class T_User { public string? uid { get; set; } public string? userName { get; set; } public string? passWord { get; set; } public bool isEnable { get; set; } = true; public DateTime? lastLoginTime { get; set; } public DateTime createTime { get; set; } public string? groupId { get; set; } public bool isManager { get; set; } /// <summary> /// 一个用户只能属于一个商户 /// </summary> public virtual T_Group? Group { get; set; } }View Code
User_Config
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
using CoreDbContext.DbDtos; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; using System.Collections.Generic; using System.Text; namespace CoreDbContext.DbConfigs { internal class T_UserConfig : IEntityTypeConfiguration<T_User> { public void Configure(EntityTypeBuilder<T_User> builder) { builder.ToTable("T_Users"); builder.HasKey(A => A.uid); builder.Property(A => A.uid).HasColumnType("varchar(64)").HasComment("主键"); builder.Property(A => A.userName).HasColumnType("varchar(64)").HasComment("登录账户"); builder.Property(A => A.passWord).HasColumnType("varchar(512)").HasComment("密码,密文"); builder.Property(A => A.groupId).HasColumnType("varchar(64)").HasComment("所属商户"); builder.Property(A => A.isManager) .HasComment("是否是平台管理员,否为商家端登录用户"); //builder.HasQueryFilter(A => A.isEnable == true); //一对多主外键配置 builder.HasOne<T_Group>(A => A.Group).WithMany().HasForeignKey(A => A.groupId); } } }View Code
项目CoreDbContext 的项目文件为:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.6" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.6"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> </ItemGroup> </Project>
关于co的 first 搭建可参考鄙人的博客
Net6/NetCore3.1搭建codeFirst 【支持多dbcontext】并接合TransactionScope 完成事务操作
Net5 控制台应用程序引入EFCore+CodeFirst
Net5 EFCore CodeFirst FluentApi关系配置
Net5 EfCore CodeFirst 乐观锁 RowRersion
3、swapCommon 公共方法类库
这个类库没用到哦
@天才卧龙的博客
标签:set,速建,get,DI,Options,options,using,DbSet,public From: https://www.cnblogs.com/chenwolong/p/16791911.html