使用 Cake 推送 NuGet 包到 AzureDevops 的 Artifacts 上

大家好,我最近在想如何提交代码的时候自动的打包 NuGet 然后发布到 AzureDevOps 中的 Artifacts,在这个过程中踩了很多坑,也走了很多弯路,所以这次篇文章就是将我探索的结果和我遇到的一些问题整理分享给大家。

我的上一篇关于 CI/CD 的文章《使用 Gitlab CI/CD 实现自动化发布站点到 IIS》 中是使用脚本的形式实现的,后来有园友在下面评论说可以使用 Cake(C# Make) 这个工具来实现其中的功能,所以本次就不用了脚本了。有时间会使用 Cake 对它进行改造。

整体思路:

  1. 首先介绍下 CakeAzureDevops Pipelines/Artifacts 怎么使用

  2. 接着配置 AzureDevops Pipelines

  3. 创建 AzureDevops Artifacts (NuGet 服务端)

  4. AzureDevops 配置 PAT (Personal Access Tokens) 和 Pipelines 所需的 Variables(变量)

  5. Cake 增加打包、推送 NuGet 包代码。

  6. 最后查看运行结果

使用到的工具及版本:

dotnet core 2.2

cake 0.33.0

PowerShell、NuGet、CredentialProvider

AzureDevops Pipelines 和 AzureDevops Artifacts

  • Cake 的全称是 C# Make,它是一个跨平台的自动化构建系统,基于 C# DSL,所以可以用我们熟悉的 C# 语言来替换掉我们之前使用脚本的构建方式。使用它我们能非常方便的编译代码,复制文件和文件夹,当然还可以运行单元测试以以确保我们的代码没有问题,我们本次的 NuGet 发布到 Artifacts 它占很重要的地位。

  • AzureDevops 的前身是 VSTS,它提供了 Repos、Pipelines、Boards、Test Plans、Artifacts:

    • Repos 提供 Git 存储库,用于代码的源代码控制,你可以直接引入你在 GitHub 上的仓储。

    • Pipelines 提供构建和发布服务,以支持应用程序的持续集成和交付(CI/CD)

    • Boards 提供了一套 Agile 工具,支持使用看板和 Scrum 方法规划和跟踪工作,代码缺陷管理等等,类似的工具有腾讯的 TAPD、阿里的 云效、华为云的 DevCloud 等等。

    • Test Plans 提供了多种测试应用程序的工具,包括手动/探索性测试和持续测试

    • Artifacts 允许团队从公共和私人来源共享 Maven,npm 和 NuGet 包。
      协作工具,包括可自定义的团队仪表板和可配置的小部件,以共享信息,进度和趋势; 用于共享信息的内置 wiki; 可配置的通知等。

  • CredentialProvider 是凭据提供程序,当我们进行 NuGet Push 时需要进行身份验证,只需要将它放在 NuGet 程序的下即可。

本次案例我已经发布到 GitHub 上了:https://github.com/WuMortal/CakePushNuGet.Example

安装:这里我使用 dotnet core 进行演示,cake 还支持 .NET Framework、Mono。首先我们需要安装 cake,借助 dotnet tool 这个命令。

dotnet tool install --global cake.tool --version 0.33.0

安装成功会出现如下提示:

640?wx_fmt=jpeg

cake 的使用方式非常简单,而且还是 C# 语法相信应该是很容易就能理解的。

这里首先定义了一个 target 变量,它里面保存的就是我们将要执行的 Task(任务)的名称。接着可以看到在在代码块中定义了许多的 Task,这里就是具体需要执行的 “任务”,第一个任务是还原项目的依赖,其实核心代码就一行 DotNetCoreRestore(solution);,第二个任务是生成项目,需要说明的是第三个任务其实是将前面两个任务整合到一起。你也可以在中第二个任务 .IsDependentOn ("Restore") 调用第一个任务,当然 var target = Argument ("target", "Demo"); 就需要改为 var target = Argument ("target", "Build"); 了,这个看个人喜好了。

640?wx_fmt=jpeg

var rootPath = "../";var srcPath = rootPath + "src/";var solution = srcPath + "Wigor.CakePushNuGet.Example.sln";var target = Argument ("target", "Demo");Task ("Restore")  .Description ("还原项目依赖")  .Does (() => {        Information ("开始执行还原项目依赖任务");    DotNetCoreRestore (solution);  });Task ("Build")  .Description ("编译项目")  .Does (() => {    Information ("开始执行编译生成项目任务");        DotNetCoreBuild (solution, new DotNetCoreBuildSettings {        NoRestore = true,        Configuration = "Release"    });  });Task ("Demo")  .IsDependentOn ("Restore")  .IsDependentOn ("Build")  .Does (() => {    Information ("所有任务完成");  });RunTarget (target);

cake 编写好后我们就可以尝试运行它,这里我的 cake 路径是 build/build.cake 大家可以根据具体情况更改 ,命令如下:

dotnet cake build/build.cake -verbosity=diagnostic

640?wx_fmt=jpeg

可以看到这里的 cake 已经运行成功了,它会将我们每个任务运行的结果和信息显示在控制台上。

640?wx_fmt=jpeg

到这里相信大家对 cake 是干什么了有点了解吧,有关它跟多的使用方法可以访问官网:https://cakebuild.net/

首先你需要一个 Microsoft 账号或者 GitHub 账号,登录地址为:https://dev.azure.com,登录之后你需要创建一个项目,这里我已经创建好一个项目了,首先我们点击 Pipelines 选择 Builds,之后会出现如下界面,点击 New Pipeline。然后跟着我下面图片的步骤一步一步来就行。

640?wx_fmt=jpeg

如果你的仓储就在 AzureDevops上那么直接选 Azure Repos Git 就行。

640?wx_fmt=jpeg

这里你的账号是 GitHub 授权登录的话会先跳转到授权界面可能会跳转多次,同意即可。

640?wx_fmt=jpeg
640?wx_fmt=jpeg

删除我选中的代码,因为我不打算用 AzureDevops Pipelines 的脚本来执行本次操作,它做的只是提供我们 cake 运行的环境。

640?wx_fmt=jpeg

更换为如下脚本,PowerShell.exe -file ./cake.ps1 是指使用 PowerShell 运行我们的 cake.ps1 文件,关于 cake.ps1 文件后面会介绍,这里我们先这样写,接着点击 Save and run

640?wx_fmt=jpeg

trigger:- masterpool:  vmImage: 'windows-latest'steps:- script: PowerShell.exe -file ./cake.ps1  displayName: 'Push NuGet Package'

可以看到问们管道的运行出现了错误,那是因为我们上面在运行了 cake.ps1 这个脚本,但是我们现在还没有创建这个脚本。

640?wx_fmt=jpeg

回到我们的项目中,将 AzureDevops Pipelines 创建的 azure-pipelines.yml 文件 pull 到我们本地。

640?wx_fmt=jpeg

接着我们编写我们下面缺少的 cake.ps1 文件,它做的事情就是将我们之前手动在 cmd 中运行的命令放入了一个 PowerShell 脚本文件中,Linux 平台的话就编写一个 shell 脚本。

640?wx_fmt=jpeg

dotnet tool install --global cake.tool --version 0.33.0Write-Host "dotnet cake build\build.cake -verbosity=diagnostic" -ForegroundColor GREENdotnet cake build\build.cake -verbosity=diagnostic

尝试项目根目录下运行这个脚本,在 cmd 中执行 powershell .\cake.ps1,下面报了一个错。
640?wx_fmt=jpeg


我们只需要以管理员身份运行 PowerShell 然后执行 set-ExecutionPolicy RemoteSigned 即可

640?wx_fmt=jpeg

640?wx_fmt=jpeg

然后再次运行 powershell .\cake.ps1 或者命令,可以看到正确的输出了

640?wx_fmt=jpeg

OK,这次我们推送(git push)下代码,在到 AzureDevops Pipelines 看看我们执行结果。
640?wx_fmt=jpeg

点进去可以看到整个执行的过程,如果报错了也可以从这里看到出错的信息

640?wx_fmt=png

如果是 powershell 报错 AzureDevops Pipelines 是不会显示执行失败的,如果没得到你想要的结果你就需要点开认真的分析你的脚本了。

前面已经讲过了如果使用 cake 和 在 AzureDevops Pipelines 下执行 cake。下面我们需要创建一个 NuGet Repository,这里我使用 AzureDevops 提供的 Artifacts。

640?wx_fmt=png
640?wx_fmt=jpeg
640?wx_fmt=png

这里面会用的就是 package source URL 和下面命令中的 -ApiKey 中的 AzureDevOps,还有这里我们需要将 NuGet + Credentials Provider 下载到我们的本地,如果你的运行环境是 Linux 或其他可以在 microsoft/artifacts-credprovider 的 GitHub 上获取对应平台的这两个包, 点击查看 GitHub 地址。

上面说过了我们推送 NuGet 包到 Artifacts 时候是需要为两个参数提供指的的 -UserName 和 -Password,这里的 UserName 我们可以随意填,但是 Password 填的的是我们创建的 PAT。

640?wx_fmt=png
640?wx_fmt=jpeg

这是选择我们 PAT 所拥有的权限,需要点击 Show all scopes 找到 Packaging 勾选 Red,wirte,& manage

640?wx_fmt=png

我们可以看到我们的 PAT ,需要注意的是这个 token 只会出现一次,你需要将它保存好,如果忘记了,那么可以点击 Regenerate 重新获取 token。

640?wx_fmt=png

在 上一篇文章 中我说过了为什么需要变量,这里就不重复了,有兴趣的可以看看。下面开始添加我们需要的变量。

640?wx_fmt=png
640?wx_fmt=jpeg

我们需要添加的变量有四个,分别是 NUGET_REPOSITORY_API_URLNUGET_REPOSITORY_API_KEYUSERNAMEPASSWORD

  • NUGET_REPOSITORY_API_URL:就是我们在创建 AzureDevops Artifacts 后出现的 package source URL

  • NUGET_REPOSITORY_API_KEY:就是那个 -ApiKey 参数的值 AzureDevOps

  • USERNAME:这个上面说过了可以随便填。

  • PASSWORD:这个就是之前创建的 PAT。

点击保存(Save & queue)或者 Ctrl + s 保存。

640?wx_fmt=jpeg

这里为已经封装过了的工具类包含了打包和推送方法,地址:NuGet.Tool.cake

using System;using System.Collections.Generic;using System.Linq;using Cake.Common.Tools.DotNetCore;using Cake.Common.Tools.DotNetCore.Pack;using Cake.Common.Tools.NuGet;using Cake.Common.Tools.NuGet.List;using Cake.Core;using NuGet.Packaging;public class NuGetTool {    public ICakeContext CakeContext { get; }    public string RepositoryApiUrl { get; }    public string RepositoryApiKey { get; }    public string UserName { get; set; }    public string Password { get; set; }    private NuGetListSettings ListSettings => new NuGetListSettings {        AllVersions = true,        Source = new string[] { this.RepositoryApiUrl }    };    private DotNetCorePackSettings BuildPackSettings (string packOutputDirectory) => new DotNetCorePackSettings {        Configuration = "Release",        OutputDirectory = packOutputDirectory,        IncludeSource = true,        IncludeSymbols = true,        NoBuild = false    };    private NuGetTool (ICakeContext cakeContext) {        CakeContext = cakeContext;        RepositoryApiUrl = cakeContext.Environment.GetEnvironmentVariable ("NUGET_REPOSITORY_API_URL");        RepositoryApiKey = cakeContext.Environment.GetEnvironmentVariable ("NUGET_REPOSITORY_API_KEY");        UserName = cakeContext.Environment.GetEnvironmentVariable ("USERNAME");        Password = cakeContext.Environment.GetEnvironmentVariable ("PASSWORD");        CakeContext.Information ($"获取所需参数成功:{RepositoryApiUrl}");    }    public static NuGetTool FromCakeContext (ICakeContext cakeContext) {        return new NuGetTool (cakeContext);    }    public void Pack (List<string> projectFilePaths, string packOutputDirectory) {        projectFilePaths.ForEach (_ => CakeContext.DotNetCorePack (_, BuildPackSettings (packOutputDirectory)));    }    public void Push (List<string> packageFilePaths) {        foreach (var packageFilePath in packageFilePaths) {            CakeContext.NuGetAddSource (                "wigor",                this.RepositoryApiUrl,                new NuGetSourcesSettings {                    UserName = this.UserName,                    Password = this.Password                });            CakeContext.NuGetPush (packageFilePath, new NuGetPushSettings {                Source = "wigor",                ApiKey = this.RepositoryApiKey            });        }    }}

在项目的 build/ 下创建 nuget.tool.cake 文件(build/nuget.tool.cake) 拷贝上面的代码。

这里参考了最开始提到的园友的项目,非常感谢它的贡献,GitHub 地址如下:cake.example

在创建 AzureDevops Artifacts 的时候那不是提供了 NuGet + Credentials Provider 的下载地址嘛,现在把它解压到我们项目的 build\tool\ 下。再次说明这里我是 Windows 环境,如果你的运行环境是 Linux 或其他可以在 microsoft/artifacts-credprovider 的 GitHub 上获取对应平台的这两个包, 点击查看 GitHub 地址。

640?wx_fmt=jpeg

修改 cake.ps1,只是增加了 NuGet.exe 的环境变量,因为不加到时候 cake 会找不到 NuGet.exe,或许还有其他办法这里就先这么干,如果各位还有更方便的方法可以在下面留言,感谢!

[string]$SCRIPT = 'build/build.cake'[string]$CAKE_VERSION = '0.33.0'$NUGET_EXE = "build/tool/NuGet.exe"$NUGET_DIRECTORY = Get-ChildItem -Path $NUGET_EXE$NUGET_DIRECTORY_NAME=$NUGET_DIRECTORY.DirectoryName$ENV:Path += ";$NUGET_DIRECTORY_NAME"dotnet tool install --global cake.tool --version $CAKE_VERSION[string]$CAKE_ARGS = "-verbosity=diagnostic"Write-Host "dotnet cake $SCRIPT $CAKE_ARGS $ARGS" -ForegroundColor GREENdotnet cake $SCRIPT $CAKE_ARGS $ARGS

修改 build.cake 文件,看着是多了很多东西其实就多了两个 Task (任务) 分别是: pack(打包) 和 push(推送包),这里需要大家需要修改的就是 solution 和 project 两个变量,将其修改为自己的解决方案名称和需要打包的项目名称。

#reference "NuGet.Packaging"#load nuget.tool.cakevar target = Argument ("target", "PushPack");var rootPath = "../";var srcPath = rootPath + "src/";var solution = srcPath + "Wigor.CakePushNuGet.Example.sln";var project = GetFiles (srcPath + "Wigor.CakePushNuGet.HelloWorld/*.csproj");var nugetPakcageDirectory = $"{srcPath}nugetPackage/";var nugetTool = NuGetTool.FromCakeContext (Context);Task ("Restore")  .Description ("还原项目依赖")  .Does (() => {        Information ("开始执行还原项目依赖任务");    DotNetCoreRestore (solution);  });Task ("Build")  .Description ("编译项目")  .Does (() => {    Information ("开始执行编译生成项目任务");        DotNetCoreBuild (solution, new DotNetCoreBuildSettings {        NoRestore = true,        Configuration = "Release"    });  });Task ("UnitTest")  .Description ("单元测试")  .Does (() => {    Information ("开始执行单元测试任务");        DotNetCoreTest(solution);  });Task ("Pack")  .Description ("Nuget 打包")  .Does (() => {    Information ("开始执行打包任务");        EnsureDirectoryExists (nugetPakcageDirectory);    var packageFilePaths = project.Select (_ => _.FullPath).ToList ();    nugetTool.Pack (packageFilePaths, nugetPakcageDirectory);  });Task ("Push")  .Description ("Nuget 发布")  .Does (() => {    Information ("开始执行 Nuget 包发布任务");    var packageFilePaths = GetFiles ($"{nugetPakcageDirectory}*.symbols.nupkg").Select (_ => _.FullPath).ToList ();    nugetTool.Push(packageFilePaths);  });Task ("PushPack")  .Description ("发布 Nuget 包")  .IsDependentOn ("Restore")  .IsDependentOn ("Build")  .IsDependentOn ("Pack")  .IsDependentOn ("Push")  .Does (() => {    Information ("所有任务完成");  });RunTarget (target);

最后我们推送修改后的代码,查看执行结果看看 NuGet 包是否发布到 AzureDevops Artifacts 上。

640?wx_fmt=png

至此已经实现了 使用 Cake 推送 NuGet 包到 AzureDevops 的 Artifacts 上,你如果不熟悉 AzureDevops Pipelines 你也可以用其他的 CI/CD 工具来执行。

在整个尝试过程中肯定会出现一些问题,不要着急认真分析,看看 AzureDevops Pipelines 上给出的提示,也可以现在本机跑一下看看是否正常。出现问题第一步查看错误信息,看看有没有错误信息(基本都有),然后根据错误信息去分析是我们的那个地方出错了,顺序是 cake.ps1 --> build.cake --> nuget.tool.cake,然后是所需的 PAT 的权限是否勾选,AzureDevops Pipelines 变量是否配置并且是 URL、Key 什么的都是正确,再然后就是 百度、Google。最后你可以在评论区留言(分享你碰到的问题以及解决方法)。

原文地址:https://www.cnblogs.com/AMortal/p/11100669.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【NOI2013】树的计数【树的遍历】【期望】

传送门 题意&#xff1a;给定一棵nnn个点的树的DFS和BFS序&#xff0c;求树高期望。 n≤2e5n \leq 2e5n≤2e5 首先根据BFS序将树点分层&#xff0c;一定切记先自己把树点分层&#xff0c;这样实际上是在排除一部分情况。 将每一层第一个点打标记&#xff0c;答案就是期望标记…

Codeforces Round #632 (Div. 2) C. Eugene and an array 思维 + 前缀和

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给定一个长度为nnn的序列aaa&#xff0c;定义一段区间为好区间是这段区间的所有连续子区间的和都不为000&#xff0c;求好区间的个数。 思路&#xff1a; 套路题&#xff0c;定义aia_iai​的前缀和bi∑j1i…

C++中vector返回值的最高效返回

返回值优化&#xff08;RVO&#xff09; std::vector<int> get_vector() {std::vector<int> v {1, 2, 3, 4, 5};return v; // 依赖编译器进行返回值优化&#xff0c;消除多余的拷贝 }虽然看起来像是在返回一个局部变量&#xff08;通常会引发拷贝或者移动&…

了解Kubernetes主体架构(二十八)

前言 Kubernetes的教程一直在编写&#xff0c;目前已经初步完成了以下内容&#xff1a;1&#xff09;基础理论2&#xff09;使用Minikube部署本地Kubernetes集群3&#xff09;使用Kubeadm创建集群接下来还会逐步完善本教程&#xff0c;比如Helm、ELK、Windows Serv…

【NOI2013】快餐店【基环树】【树的直径】【set】

传送门 题意&#xff1a;给一棵nnn个点的基环树&#xff0c;找一个点&#xff08;可以在边上&#xff09;&#xff0c;求所有节点到这个点的最大值的最小值。 n≤1e5n \leq1e5n≤1e5 先考虑一棵普通树的情况 显然是直径长度的一半 因为如果有个点大于直径长度的一半&#x…

Codeforces Round #632 (Div. 2) F. Kate and imperfection 数论 + 贪心

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; n≤5e5n\le5e5n≤5e5 思路&#xff1a; 首先有个显然的结论&#xff1a;当往集合中加入一个数xxx的时候&#xff0c;如果存在d∣xd|xd∣x且ddd不在集合中&#xff0c;那么加入ddd一定比加入xxx更优。 也就是…

.NET开发框架(二)-框架功能简述

本框架为响应式SPA框架&#xff0c;支持PC与手机端的屏幕自适应。手机展示效果视频在文章末尾查看。框架入口地址&#xff1a;http://letyouknow.net/1、框架登录界面&#xff0c;输入账号与密码&#xff0c;点击立即登录2、框架主界面&#xff0c;左-右结构&#xff0c;左边为…

杜教筛复杂度证明

我们实际上求的是这玩意 T(n)n∑i1n(T(i)T(ni))T(n)\sqrt{n}\sum_{i1}^{\sqrt{n}}(T(i)T(\frac{n}{i}))T(n)n​i1∑n​​(T(i)T(in​)) 我们只需要考虑 T(n)n∑i1n(ini)T(n)\sqrt{n}\sum_{i1}^{\sqrt{n}}(\sqrt i\sqrt\frac{n}{i})T(n)n​i1∑n​​(i​in​​) 对于之后的项&a…

Codeforces Round #632 (Div. 2) E. Road to 1600 构造好题

传送门 文章目录题意&#xff1a;思路题意&#xff1a; 直接白嫖 思路 首先不难发现&#xff0c;n≤2n\le2n≤2的时候是无解的。 现在我们来构造n3n3n3的情况&#xff0c;通过打表可以发现如下矩阵是符合题目要求的&#xff1a; 179325486\begin{array}{ccc} 1&7&9…

SiteServer CMS 新版本 V6.11(2019年7月1日发布)

欢迎来到 SiteServer CMS V6.11版本&#xff08;.NET CORE V7.0预览版本将推迟至2019年9月1日发布&#xff09;&#xff0c;经过两个月的连续迭代开发&#xff0c;V6.11 版本新增了采集插件以及多项BUG修复&#xff1a;SS.Gather 页面采集插件页面采集插件将在V6.11版本中正式提…

【NOI2016】循环之美【莫比乌斯反演】【整除分块】【杜教筛】【类杜教筛】

传送门 题意&#xff1a;给定n,m,kn,m,kn,m,k,求1≤x≤n,1≤y≤m1\leq x\leq n,1\leq y\leq m1≤x≤n,1≤y≤m时xyx \over yyx​中数值不同的纯循环小数或整数的个数。 n≤109,m≤109,k≤2103n \leq 10^9,m\leq10^9,k\leq2\times10^3n≤109,m≤109,k≤2103 显然只需要考虑最简…

P1020 [NOIP1999 普及组] 导弹拦截 Dilworth定理 + dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 对于第一问直接输出最长不严格下降子序列即可&#xff0c;第二问是Dilworth定理&#xff0c;变形比较多&#xff0c;之前也写过类似的&#xff0c;这里贴个证明。 //#pragma GCC optimiz…

参数传递机制之JWT

1. 什么是 JWTJWT 其全称为&#xff1a;JSON Web Token&#xff0c;简单地说就是 JSON 在 Web 上的一种带签名的标记形式。官方的定义如下&#xff1a;JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.…

【NOI2009】诗人小G【决策单调性dp】

传送门 设句子加上空格长度前缀和为sss 转移方程为 fimin⁡1≤j<i{fj∣si−sj−L−1∣P}f_i\min_{1\leq j<i}\{f_j|s_i-s_j-L-1|^P\}fi​1≤j<imin​{fj​∣si​−sj​−L−1∣P} 不难发&#xff08;cai&#xff09;现&#xff08;chu&#xff09;决策具有单调性 …

Codeforces Round #709 (Div. 1) B. Playlist 链表维护 + bfs

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 紧跟刘爷脚步补题。 不难想到用链表维护下一个数是什么&#xff0c;这样就跟以前做过的一个题差不多了&#xff0c;首先将初始的时候删掉的点的前一个点即为题目中的AAA入队&#xff0c;让…

浅谈ASP.NET Core中IOC与DI的理解和使用

说起IOC和DI,使用过ASP.NET Core的人对这两个概念一定不陌生&#xff0c;早前&#xff0c;自己也有尝试过去了解这两个东西&#xff0c;但是一直觉得有点很难去理解&#xff0c;总觉得对其还是模糊不清&#xff0c;所以&#xff0c;趁着今天有空&#xff0c;就去把两个概念捋清…

Codeforces Round #715 (Div. 1) C. Complete the MST 补图 + 思维 + 最小生成树

传送门 文章目录题意&#xff1a;思路题意&#xff1a; 给你一张nnn个点mmm个边的图&#xff0c;mmm条边是给定的&#xff0c;要求你给未给定的边赋值一个边权&#xff0c;使得所有边权异或和为000&#xff0c;求所有满足这种情况的图中最小生成树边权和最小的&#xff0c;输出…

一个通用数据库操作组件DBUtil(c#)、支持SqlServer、Oracle、Mysql、postgres、SQLITE

这是一个.net下操作数据库(结构数据库)的工具类&#xff0c;支持sqlserver、oracle、mysql、postgres、sqlite、access等常见数据库。注意&#xff1a;它并不是一个orm工具(常见的orm框架如&#xff1a;EF、Dapper等)。2.1 引入DBUtil依赖1. 首先打开vs(推荐vs2019)&#xff0c…

【NOI2012】迷失游乐园【概率期望】【换根dp】【基环树】

传送门 题意&#xff1a;给一棵nnn个点的带边权树或基环树&#xff0c;随机选一个点作为起点&#xff0c;每次随机走到一个相邻未走过的位置&#xff0c;直到无路可走。求期望路径长度。 n≤105n \leq 10^5n≤105,为基环树时环的大小不超过202020 先考虑树怎么做废话 先只考…

Educational Codeforces Round 37 (Rated for Div. 2) E. Connected Components? 暴力 + 补图的遍历

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; n≤2e5,m≤2e5n\le2e5,m\le2e5n≤2e5,m≤2e5。 思路&#xff1a; 这是题是我上个题的一部分&#xff0c;算是个小知识点&#xff0c;暴力能过。 直接维护一个setsetset&#xff0c;让后遍历所有点&#xff…