1, 啟用 ShadowCopy
如何啟用, 參見:
What's new in ASP.NET Core 6.0 | Microsoft Learn
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- To customize the asp.net core module uncomment and edit the following section.
For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->
<system.webServer>
<handlers>
<remove name="aspNetCore"/>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified"/>
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout">
<handlerSettings>
<handlerSetting name="experimentalEnableShadowCopy" value="true" />
<handlerSetting name="shadowCopyDirectory" value="../ShadowCopyDirectory/" />
<!-- Only enable handler logging if you encounter issues-->
<!--<handlerSetting name="debugFile" value=".\logs\aspnetcore-debug.log" />-->
<!--<handlerSetting name="debugLevel" value="FILE,TRACE" />-->
</handlerSettings>
</aspNetCore>
</system.webServer>
</configuration>
需要注意的是:
processPath
arguments
這兩個參數(shù)要替換掉, 否則站點啟動不了:
processPath="dotnet" arguments="CPS_SUP.WebApi.N5.dll"
arguments
這個參數(shù)要替換成自己的項目啟動項。
2, 在 Plugin 模式下的問題
- 如果子項目是用
輸出目錄
的方式將 DLL 輸出到主項目的Debug|Release
下,主項目啟動的時候,掃描DLL 并進行加載的話 (簡單的Plugin
模式),上面的設(shè)置對子項目無效,仍然會提示文件被占用。
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<OutputPath>..\CPS_SUP.WebApi.N5\bin\Debug\net6.0\</OutputPath>
<!--移除輸出目錄中的 net6.0 子文件夾, 直接輸出到 debug, release 目錄中-->
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<!--將引用的相關(guān)DLL一并輸出, 否則, 不會輸出-->
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<OutputPath>..\CPS_SUP.WebApi.N5\bin\Release\net6.0\</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
- 除非主項目直接引用這個子項目。
- 如果直接引用子項目, 會在
{app}.deps.json
里面把相關(guān)的子項目信息都列出來。但是Plugin
的目的, 就是了和主項目脫離關(guān)系, 況且?guī)资畟€Plugin
,每個Plugin
都是單獨編譯,所以不考慮這種方式。 - 我試著安裝
.NET 7 RC2
的Hosting bundle
, (windows 2008 R2
), 但是 目錄:C:\Program Files\IIS\Asp.Net Core Module\V2
下面對應(yīng)的版本仍然是16.xxx
而不是最新的17.xxx
, 不知道咋回事。.NET 7
的嘗試到此為止, 況且目前還只是RC
版。
好像陷入了無解的境地。。。
但是。。。
把 主項目的 {appp}.deps.json
文件刪掉。。。(參見: sdk/runtime-configuration-file.md at main · dotnet/sdk (github.com) )
MyApp.deps.json - A list of dependencies, compilation dependencies and version information used to address assembly conflicts. Not technically required, but required to use the servicing or package cache/shared package install features, and to assist during roll-forward scenarios to select the newest version of any assembly that exists more than once in the application and framework(s). If the file is not present, all assemblies in the current folder are used instead.
Not technically required
明確了這個文件不是必須的.
嘗試把這個文件移除/改名之后, 就不會在提示文件被占用了。這說明:當(dāng)前版本的 shadowCopy
只是是監(jiān)控了 {app}.deps.json
中列出的文件
對 EF 的影響
上面把 {app}.deps.json
文件刪掉之后, 執(zhí)行帶有 EF 查詢的方法, 報了這么一個異常:
System.PlatformNotSupportedException: Strings.PlatformNotSupported_DataSqlClient
at Microsoft.Data.SqlClient.SqlConnectionStringBuilder..ctor(String connectionString)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.<>c.<get_IsMultipleActiveResultSetsEnabled>b__7_0(String cs)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerConnection.get_IsMultipleActiveResultSetsEnabled()
at Microsoft.EntityFrameworkCore.SqlServer.Query.Internal.SqlServerCompiledQueryCacheKeyGenerator.GenerateCacheKey(Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.FirstOrDefaultAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
為解決這個問題, 把發(fā)布選項的目標(biāo)運行時 從 可移植
改為 win-x64
, 然后發(fā)布, EF 執(zhí)行正常了..
指定 --additional-deps
上面的步驟,太麻煩, 一不小心就會把服務(wù)搞成 503
即然上面證實了 shadowCopy
只是監(jiān)控了 {app}.deps.json
中列出的文件, 那能不能讓它多監(jiān)控一些文件呢?
要實現(xiàn)這個目的有兩個方法:
- 把每個 Plugin 都引用進主項目里去, 這和 Plugin 模式?jīng)_突。
- 用 --additional-deps ,把目錄下面所有的 xxx.deps.json 都列出來。
- 不要忘了原來的那個
%LAUNCHER_ARGS%
(CPS_SUP.WebApi.N5.dll)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- To customize the asp.net core module uncomment and edit the following section.
For more info see https://go.microsoft.com/fwlink/?linkid=838655 -->
<system.webServer>
<handlers>
<remove name="aspNetCore"/>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified"/>
</handlers>
<aspNetCore
processPath="dotnet"
arguments="--additional-deps CPS_SUP.Biz.AXin.deps.json;CPS_SUP.Biz.Ctrip.deps.json;CPS_SUP.Biz.DC.deps.json;CPS_SUP.Biz.DDS.deps.json CPS_SUP.WebApi.N5.dll"
stdoutLogEnabled="false"
stdoutLogFile="logs\stdout"
hostingModel="InProcess">
<handlerSettings>
<handlerSetting name="experimentalEnableShadowCopy" value="true" />
<handlerSetting name="shadowCopyDirectory" value="../ShadowCopyDirectory/" />
<!-- Only enable handler logging if you encounter issues-->
<!-- <handlerSetting name="debugFile" value="logs\aspnetcore-debug.log" /> -->
<!-- <handlerSetting name="debugLevel" value="FILE,TRACE" /> -->
</handlerSettings>
</aspNetCore>
</system.webServer>
</configuration>
--additional-deps 參數(shù)的說明
這個參數(shù)有個缺點,就是不能用通配符。。。導(dǎo)致每新加一個 Plugin 都需要重新修改一下這個參數(shù)。所有的都要加上, 不在這個列表里面的相關(guān) dll 還是會被鎖定的。
這個參數(shù)的分隔符在 windows 下是 ;
還有一點注意:為避免無意中把 web.config
給覆蓋了, 應(yīng)該把這個文件設(shè)置為只讀。
日志文件
最后一個問題,日志文件也被復(fù)制到了 ShadowCopy 文件夾中去了...
要解決這個問題,只能把所有日志目錄指定站點文件外了。
不然真成掃地機器人掃狗屎,糊一地了。。。
.NET 7 中的 ShadowCopy
參見:Advanced configuration | Microsoft Learn
.NET 7 把這個功能從實驗功能升級成正式功能了。
對應(yīng)的, 把experimentalEnableShadowCopy
改成了 enableShadowCopy
。