我想将我的azure功能从net 6升级到net 8。
这里是升级前的初始csproj。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<UseNETCoreGenerator>true</UseNETCoreGenerator>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.7.0" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.4.4" />
<PackageReference Include="Azure.Storage.Files.DataLake" Version="12.2.2" />
<PackageReference Include="Microsoft.Azure.DataLake.Store" Version="1.1.21" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.5" />
<PackageReference Include="Microsoft.Azure.WebJobs.Core" Version="3.0.36" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.9.1" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.3" />
<PackageReference Include="Microsoft.Rest.ClientRuntime.Azure.Authentication" Version="2.4.1" />
<PackageReference Include="SharpZipLib" Version="1.2.0" />
<PackageReference Include="SSH.NET" Version="2016.1.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
功能代码为:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using TransferAppApp.Classes;
namespace TransferAppApp
{
public static class TransferApp
{
[FunctionName("TransferApp")]
public static async Task<object> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger log)
{
log.LogInformation("Getting query parameters");
var requestParams = context.GetInput<Dictionary<string,string>>();
try
{
log.LogInformation("Making call to TransferApp_Transfer");
var output = await context.CallActivityAsync<object>("TransferApp_Transfer", requestParams);
return output;
}
catch(Exception ex)
{
log.LogInformation($"Following error occurred during execution: {ex.Message}");
throw new Exception($"Following error occurred during execution: {ex.Message}", ex);
}
}
[FunctionName("TransferApp_Transfer")]
public static async Task<object> Transfer([ActivityTrigger] Dictionary<string,string> requestParams, ILogger log, ExecutionContext context)
{
#region Initialisation
// Request Variables
log.LogInformation("Getting query parameters");
requestParams.TryGetValue("environment", out string environment);
requestParams.TryGetValue("MasterId", out string MasterId); // 35XXX
requestParams.TryGetValue("opCoMasterId", out string opCoMasterId); // 13XXX
requestParams.TryGetValue("opCo", out string opCo);
requestParams.TryGetValue("DateToProcess", out string strDateToProcess); // yyyy-MM-dd
DateTime DateToProcess = Convert.ToDateTime(strDateToProcess);
requestParams.TryGetValue("SourceStorageType", out string SourceStorageType);
requestParams.TryGetValue("SourceAccountName", out string SourceAccountName);
requestParams.TryGetValue("SourceBlobContainer", out string SourceBlobContainer);
requestParams.TryGetValue("SourceFilePath", out string SourceFilePath);
requestParams.TryGetValue("SourceFileName", out string SourceFileName);
requestParams.TryGetValue("SendToCompany", out string strSendToCompany); // Y/N
bool SendToCompany = strSendToCompany == "Y";
requestParams.TryGetValue("SendToTARGET", out string strSendToTARGET); // Y/N
bool SendToTARGET = strSendToTARGET == "Y";
requestParams.TryGetValue("ZipOutputFile", out string strZipOutputFile); // Y/N
bool ZipOutputFile = strZipOutputFile == "Y";
requestParams.TryGetValue("UsePartialNaming", out string strUsePartialNaming); // Y/N
bool UsePartialNaming = strUsePartialNaming == "Y";
requestParams.TryGetValue("SaveToRaw", out string strSaveToRaw); // Y/N
bool SaveToRaw = strSaveToRaw == "Y";
requestParams.TryGetValue("DeleteFromSource", out string strDeleteFromSource); // Y/N
bool DeleteFromSource = strDeleteFromSource == "Y";
requestParams.TryGetValue("CompanyServerPath", out string CompanyServerPath); // /RootFolder/Folder
log.LogInformation($"SourceFileName: {SourceFileName}");
log.LogInformation($"SendToCompany: {SendToCompany}");
log.LogInformation($"SendToTARGET: {SendToTARGET}");
log.LogInformation($"ZipOutputFile: {ZipOutputFile}");
log.LogInformation($"UsePartialNaming: {UsePartialNaming}");
log.LogInformation($"SaveToRaw: {SaveToRaw}");
log.LogInformation($"DeleteFromSource: {DeleteFromSource}");
log.LogInformation($"CompanyServerPath: {CompanyServerPath}");
log.LogInformation($"Environment: {environment}");
log.LogInformation($"MasterId: {MasterId}");
log.LogInformation($"OpCoMasterId: {opCoMasterId}");
log.LogInformation($"OpCo: {opCo}");
log.LogInformation($"DateToProcess: {DateToProcess}");
log.LogInformation($"SourceStorageType: {SourceStorageType}");
log.LogInformation($"SourceAccountName: {SourceAccountName}");
log.LogInformation($"SourceBlobContainer: {SourceBlobContainer}");
log.LogInformation($"SourceFilePath: {SourceFilePath}");
// Function Variables
//string scratchFolder = Path.Combine(context.FunctionAppDirectory, "Data", Guid.NewGuid().ToString()) + @"-TARGETscratch\";
string scratchFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + @"-espscratch\");
log.LogInformation(scratchFolder);
string outboundContainer = "blout" + MasterId;
string outboundFilePath = "DEST/" + opCo + "/" + DateToProcess.ToString("yyyy/MM/dd");
bool transferResultTARGET = false;
bool transferResultCompany = false;
SettingsHelper settingsHelper;
if (!SendToCompany & !SendToTARGET)
{
log.LogInformation("Both SendToCompany and SendToTARGET are false, and so no files will be transferred. Stopping execution.");
throw new Exception("Both SendToCompany and SendToTARGET are false, and so no files will be transferred. Stopping execution.");
}
// Initialise Settings
try
{
log.LogInformation("Initialising Settings");
settingsHelper = new SettingsHelper(environment, MasterId, opCoMasterId, SendToCompany, CompanyServerPath, SendToTARGET);
}
catch (Exception ex)
{
log.LogInformation($"Failed to initialise settings: {ex.Message}");
throw new Exception($"Failed to initialise settings: {ex.Message}", ex);
}
#endregion
#region Create Scratch Directory
try
{
CreateScratchDirectory(scratchFolder, log);
}
catch (Exception ex)
{
log.LogInformation($"Failed to create scratch directory: {ex.Message}");
throw new Exception($"Failed to create scratch directory: {ex.Message}", ex);
}
#endregion
#region Get Files To Transfer
log.LogInformation("Getting Files To Transfer");
TransferHelper transferHelper = new TransferHelper(settingsHelper, log);
List<string> fileList = new List<string>();
try
{
if (string.IsNullOrEmpty(SourceFileName))
{
List<string> files = transferHelper.GetAllFilesFromPath(environment, opCoMasterId, SourceStorageType, SourceBlobContainer, SourceFilePath);
fileList.AddRange(files);
}
else
{
fileList.Add(SourceFileName);
}
}
catch (Exception ex)
{
// Delete temporary local folder
Directory.Delete(scratchFolder, true);
log.LogInformation($"Error occurred while getting list of files to transfer: {ex.Message}");
throw new Exception($"Error occurred while getting list of files to transfer: {ex.Message}", ex);
}
log.LogInformation($"Transfering {fileList.Count} files in total");
#endregion
#region Transfer All Files
bool isDownloadSuccessful;
bool isSaveSuccessful;
bool isDeleteSuccessful;
foreach (var file in fileList)
{
string localFile = scratchFolder + file;
string filename = file;
log.LogInformation($"Local File: {localFile}");
log.LogInformation($"Filename: {filename}");
try
{
isDownloadSuccessful = await transferHelper.DownloadFileToLocal(environment, opCoMasterId, SourceStorageType, SourceBlobContainer, SourceFilePath, filename, localFile);
log.LogInformation("File download a success. Zipping and transferring the file");
if (ZipOutputFile)
{
log.LogInformation("Zipping File");
localFile = CompressionHelper.ZipFile(localFile);
filename = Path.ChangeExtension(filename, ".zip");
log.LogInformation($"Local File: {localFile}");
log.LogInformation($"Filename: {filename}");
}
else
{
log.LogInformation("Not Zipping File");
}
if (SendToTARGET)
{
transferResultTARGET = transferHelper.TransferFileToTARGET(localFile, filename, UsePartialNaming);
}
if (SendToCompany)
{
transferResultCompany = transferHelper.TransferFileToCompany(localFile, filename, UsePartialNaming);
}
if (SaveToRaw)
{
isSaveSuccessful = await transferHelper.SaveToRawOutbound(outboundContainer, outboundFilePath, filename, localFile);
}
// Delete from local and blpickupTARGET container (if applicable)
File.Delete(localFile);
if (DeleteFromSource)
{
isDeleteSuccessful = await transferHelper.DeletePath(SourceStorageType, SourceBlobContainer, SourceFilePath, filename, environment, opCoMasterId);
}
}
catch (Exception ex)
{
// Delete temporary local folder
Directory.Delete(scratchFolder, true);
log.LogInformation($"Error occurred trying to transfer {file}: {ex.Message}");
throw new Exception($"Error occurred trying to transfer {file}: {ex.Message}", ex);
}
string transferResultDescription = GetTransferResult(SendToCompany, SendToTARGET, transferResultCompany, transferResultTARGET, log);
if (!string.IsNullOrEmpty(transferResultDescription))
{
Directory.Delete(scratchFolder, true);
log.LogInformation($"Failed to transfer {file}");
throw new Exception($"Failed to transfer {file}");
}
}
#endregion
Directory.Delete(scratchFolder, true);
log.LogInformation("File(s) successfully transfered");
return new
{
Success = true,
Result = "File(s) successfully transfered"
};
}
[FunctionName("TransferApp_HttpStart")]
public static async Task<HttpResponseMessage> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
[DurableClient] IDurableOrchestrationClient starter,
ILogger log)
{
// Request Parameters
log.LogInformation("Storing query parameters");
Dictionary<string, string> requestParams = new Dictionary<string, string>(GetQueryParameters(req.RequestUri.Query));
// Function input comes from the request content.
log.LogInformation("Starting new instance of TransferApp");
string instanceId = await starter.StartNewAsync("TransferApp", requestParams);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
#region Helpers
public static Dictionary<string,string> GetQueryParameters(string query)
{
query = query.Substring(1);
string[] parameters = query.Split("&");
Dictionary<string, string> result = new Dictionary<string, string>();
foreach (var parameter in parameters)
{
string[] keyValue = parameter.Split("=", 2);
result.Add(keyValue[0], keyValue[1]);
}
return result;
}
private static void CreateScratchDirectory(string scratchFolder, ILogger log)
{
if (!Directory.Exists(scratchFolder))
{
log.LogInformation("Creating Scratch Directory: " + scratchFolder);
Directory.CreateDirectory(scratchFolder);
log.LogInformation("Scratch Created!");
}
else
{
log.LogInformation("Deleting & Creating Scratch Directory: " + scratchFolder);
Directory.Delete(scratchFolder, true);
Directory.CreateDirectory(scratchFolder);
log.LogInformation("Scratch Deleted and Created!");
}
}
private static string GetTransferResult(bool SendToCompany, bool SendToTARGET, bool transferResultCompany, bool transferResultTARGET, ILogger log)
{
string errorDescription = "";
// Check Company Transfer
if (SendToCompany & transferResultCompany)
{
log.LogInformation("File successfully transfered to Company");
}
else if (SendToCompany & !transferResultCompany)
{
log.LogInformation("Failed to transfer file to Company");
errorDescription = errorDescription + "Failed to transfer file to Company. ";
}
// Check TARGET Transfer
if (SendToTARGET & transferResultTARGET)
{
log.LogInformation("File successfully transfered to TARGET");
}
else if (SendToTARGET & !transferResultTARGET)
{
log.LogInformation("Failed to transfer file to TARGET");
errorDescription = errorDescription + "Failed to transfer file to TARGET. ";
}
return errorDescription;
}
#endregion
}
}
到目前为止我所做的: 更新了 .NET 8 的项目文件: 这是升级后我的 .csproj 文件:(清理、恢复、重建等)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Classes\DataLakeGen1Helper.cs" />
</ItemGroup>
<ItemGroup>
<!-- Azure Packages -->
<PackageReference Include="Azure.Core" Version="1.44.1" />
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Azure.Security.KeyVault.Certificates" Version="4.7.0" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.7.0" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.23.0" />
<PackageReference Include="Azure.Storage.Files.DataLake" Version="12.21.0" />
<!-- Azure Functions & Durable Task -->
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.5" />
<PackageReference Include="Microsoft.Azure.WebJobs.Core" Version="3.0.41" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.6.0" />
<!-- Utility Libraries -->
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
没有部署错误,也没有构建错误。
但是运行该函数时,我收到以下错误消息:
{“消息”:“处理您的信息时出现问题 请求","ExceptionMessage":"无法加载文件或程序集 'System.Memory.Data,版本=6.0.0.0,文化=中性, PublicKeyToken=cc7b13ffcd2ddd51'。系统找不到该文件 指定。","ExceptionType":"System.IO.FileNotFoundException","StackTrace":" 在Azure.RequestFailedException.AppendContentAndHeaders(响应 响应、StringBuilder 消息生成器) 在 Azure.RequestFailedException.CreateExceptionDetails(响应响应, RequestFailedDetailsParser 解析器) 在 Azure.RequestFailedException..ctor(响应响应,异常 内部异常,RequestFailedDetailsParser 详细信息解析器) 在 Azure.Storage.Blobs.ContainerRestClient.CreateAsync(Nullable
2元数据,Nullable1 timeout, IDictionary
1阻止EncryptionScopeOverride, CancellationToken(取消令牌) 在 Azure.Storage.Blobs.BlobContainerClient.CreateInternal(PublicAccessType publicAccessType,IDictionary1 access, String defaultEncryptionScope, Nullable
2元数据, BlobContainerEncryptionScopeOptions cryptoScopeOptions,布尔值 异步、CancellationToken 取消令牌) 在 Azure.Storage.Blobs.BlobContainerClient.CreateIfNotExistsAsync(PublicAccessType publicAccessType,IDictionary2 metadata, BlobContainerEncryptionScopeOptions encryptionScopeOptions, Boolean async, CancellationToken cancellationToken, String operationName)\r\n at Azure.Storage.Blobs.BlobContainerClient.CreateIfNotExistsInternal(PublicAccessType publicAccessType, IDictionary
1 响应任务) 在 DurableTask.AzureStorage.Storage.BlobContainer.CreateIfNotExistsAsync(CancellationToken 取消令牌)中 //src/DurableTask.AzureStorage/Storage/BlobContainer.cs:第 51 行2 metadata, BlobContainerEncryptionScopeOptions encryptionScopeOptions, CancellationToken cancellationToken)\r\n at DurableTask.AzureStorage.Storage.ClientResponseExtensions.DecorateFailure[T](Task
在 DurableTask.AzureStorage.Partitioning.AppLeaseManager.CreateContainerIfNotExistsAsync() 在 //src/DurableTask.AzureStorage/Partitioning/AppLeaseManager.cs:line 207 在 DurableTask.AzureStorage.AzureStorageOrchestrationService.GetTaskHubCreatorTask() 在 //src/DurableTask.AzureStorage/AzureStorageOrchestrationService.cs:line 第371章 在 DurableTask.AzureStorage.AzureStorageOrchestrationService.EnsureTaskHubAsync() 在 //src/DurableTask.AzureStorage/AzureStorageOrchestrationService.cs:line 第352章 在 DurableTask.AzureStorage.AzureStorageOrchestrationService.GetOrchestrationStateAsync(字符串 instanceId、布尔 allExecutions、布尔 fetchInput) 中 //src/DurableTask.AzureStorage/AzureStorageOrchestrationService.cs:line 1827年 在 Microsoft.Azure.WebJobs.Extensions.DurableTask.AzureStorageDurabilityProvider.GetOrchestrationStateWithInputsAsync(字符串 实例 ID,布尔值 showInput) 中 //src/WebJobs.Extensions.DurableTask/AzureStorageDurabilityProvider.cs:line 81 在 Microsoft.Azure.WebJobs.Extensions.DurableTask.DurableClient.Microsoft.Azure.WebJobs.Extensions.DurableTask.IDurableOrchestrationClient.GetStatusAsync(String instanceId、布尔值 showHistory、布尔值 showHistoryOutput、布尔值 显示输入)中 //src/WebJobs.Extensions.DurableTask/ContextImplementations/DurableClient.cs:line 第465章 在 Microsoft.Azure.WebJobs.Extensions.DurableTask.HttpApiHandler.HandleGetStatusRequestAsync(HttpRequestMessage 请求,字符串实例Id,可为空`1 返回InternalServerErrorOnFailure,IDurableOrchestrationClient 现有客户端)中 //src/WebJobs.Extensions.DurableTask/HttpApiHandler.cs:第 635 行
在 Microsoft.Azure.WebJobs.Extensions.DurableTask.HttpApiHandler.HandleRequestAsync(HttpRequestMessage 请求)中 /_/src/WebJobs.Extensions.DurableTask/HttpApiHandler.cs:第 376 行”}
所以我走进了兔子洞,朝这个方向尝试了不同的事情。(还有一些其他问题这里)
尝试手动引用System.Memory.Data: 我为 System.Memory.Data 程序集添加了直接,并确保它存在于 bin\Debug 中 et8.0文件夹。
我运行了 dotnet clean、dotnet Restore 和 dotnet build 多次。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<!-- Generates runtimeconfig.json -->
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Classes\DataLakeGen1Helper.cs" />
</ItemGroup>
<ItemGroup>
<!-- Azure Packages -->
<PackageReference Include="Azure.Core" Version="1.44.1" />
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Azure.Security.KeyVault.Certificates" Version="4.7.0" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.7.0" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.23.0" />
<PackageReference Include="Azure.Storage.Files.DataLake" Version="12.21.0" />
<!-- Azure Functions & Durable Task -->
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.5" />
<PackageReference Include="Microsoft.Azure.WebJobs.Core" Version="3.0.41" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.6.0" />
<!-- Utility Libraries -->
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="System.Memory.Data" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\web.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Reference Include="System.Memory.Data">
<HintPath>bin\Debug\net8.0\System.Memory.Data.dllSystem.Memory.Data.dll</HintPath>
<Private>true</Private>
</Reference>
</ItemGroup>
</Project>
但我仍然遇到同样的错误。
我是 dot.net 的菜鸟,很高兴探索您可能有的任何其他线索或建议。非常感谢您的帮助
与其直接将 .csproj 从 .NET 6 更新到 .NET 8,不如创建一个 .NET 8 进程内持久函数,然后按照 @Andrew B 的建议添加所需的代码以及必要的包在评论里。
该问题可能是由于版本之间的冲突而发生的。
按照以下步骤创建默认的 .NET 8 进程内持久函数。
创建后,它将在 .csproj 文件中包含以下包。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<RootNamespace>_79207235</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.6.0" />
</ItemGroup>
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="local.settings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>