修復遷移後Net Standard項目中的錯誤
接上一章,項目編譯結果如下:
解決依賴dll引用
在Net Framework項目的引用如下:
各引用和作用:
- log4net(1.10.0.0) 用於寫框架日誌
- Castle.DynamicProxy(1.1.5.1) 用於代理類生成
- Micosoft.Practice.EnterpiseLibrary 微軟企業庫,用於管理數據鏈接和緩存的功能
- System.Data.OracleClient 用於鏈接Oracle數據庫
- System.Data 用於SQL SERVER 、OLeDB、ODBC的數據庫操作
這些老的項目引用是不能直接用在Net Standard項目上的,解決過程如下:
- [解決] log4net是開源項目,從2.0.6 版開始就已經支持.NET Core,目前是2.0.8,在在開源網站和nuget上可以下載到。通過nuget引用最新的dll,可以無縫兼容
- [解決] Castle.DynamicProxy也是一個開源的項目,他也具有.NET Core版本對應的DLL(Castle.Core),只是接口和我引用的1.1.5.1的接口有一點點區別,可以調整一點代碼解決,同時把老項目的dll也引用最新的dll即可。
- [移除相關的代碼]Micosoft.Practice.EnterpiseLibrary 企業庫微軟已經很早不支持了,也沒有對應的Core版本,我的做法是檢查下代碼看看這些代碼是否能去掉,或用別的方式來實現。
- System.Data.OracleClient Net Core官方沒有出dll來實現,但是有社區已經實現了對應的dll. 目前我沒有驗證這個功能,只是將相關的類不編譯。
- System.Data 這個參考下面的章節,來解決,因爲之前這個dll包含了oledb、odbc、sqlserver的數據庫。目前微軟有Syste.Data.SqlClient.dll來兼容sql server的其他的都不支持。
新項目的引用截圖:
數據庫相關的錯誤修訂
MS Sql Server
Net 和 MS Sql Server交互大多通過Syste.Data.SqlClient.dll中相關類操作,在Core項目中,項目中通過引用Nuget中的 System.Data.SqlClient包,即可修復。
OleDB 和 ODBC
Net Core\Standard不再支持System.Data.OleDb。
目前沒有找到相關 Net Core\Standard 中官方有相關的類庫來替代。
所以在編譯Net Core\Standard項目時,通過項目文件去除相關類。
移除編譯的方式很簡單,使用文本編輯器,打開.csproj文件:
之前我們通過添加一下配置,將代碼以快捷方式添加到新項目中
<ItemGroup>
<Compile Include="..\..\Beyondbit.Framework\**\*.cs" />
</ItemGroup>
將我們不需要的功能排除掉,使用以下語法:
<ItemGroup>
<Compile Remove="..\..\Beyondbit.Framework\Data\OdbcDbClientProvider.cs" />
<Compile Remove="..\..\Beyondbit.Framework\Data\OleDbDbClientProvider.cs" />
</ItemGroup>
通過上面,新項目中,就不會出現OdbcDbClientProvider.cs文件,而老項目還有的。通過這種方式排除和olddb和odbc相關的類。
Oracle
Net Core\Standard不再支持System.Data.OracleClient。
微軟沒有提供相關類庫來支持,但是有開源社區有實現的版本OracleClientCore ,可以在Nuget 中下載,這個我沒有試過是否有效。
修復配置文件讀取的錯誤
Web.config App.config
在Net Core 2.0 以後是支持App.config的,在之前Net Core 中的配置不能像我們在Net Frameword中那樣讀取配置。 2.0之前Net Core讀取配置的方法,可以參考LizeZere 同學的文章《ASP.NET Core開發-讀取配置文件Configuration》和曉晨Master同學的文章《.NET Core 配置Configuration雜談》
在Net Core\Standard中是沒有web.config的概念,No ConfigurationManager in ASP.NET Core,沒錯.net core 不支持了。
不過可以採取變通的方式來解決,參考binbinxu同學的文章解決《.NET CORE 2.0 踩坑記錄之ConfigurationManager》,驗證是有效的。
App.config 讀取BUG
實測使用System.Configuration.ConfigurationManager 4.4.1 版本讀取配置時,在Web項目或者控制檯應用,都可以順利讀取。但我在vs2017創建的MSUnit的測試項目運行集成測試時,讀取失敗了。目前還沒找到方法解決,後續我會反饋BUG在github上。
編譯時報“CS0579: Duplicate 'AssemblyFileVersionAttribute' attribute”錯誤的解決辦法
當創建 .NET Core/Standard 2.0項目時,VS不會像.NET Framework項目一樣自動生成AssemblyInfo.cs文件。
而且,若是手工在項目中加入以前寫好的 AssemblyInfo.cs 文件,編譯時會報告“CS0579: Duplicate 'AssemblyFileVersionAttribute' attribute”錯誤.
參考zyl910同學的文章解決,驗證有效。
修復HttpContext問題
在我們的老項目,代碼裏面可能會判斷當前是否在Web環境下,會讀取一些以前特定的代碼,這個問題是最難處理的。如以下代碼:
可以看到編譯提示HttpContext在老項目可以,在新項目顯示不可用,並出現紅線。這是因爲在NetCore中System.Web的命名空間不在包含HttpContext類了。通過查詢一些文章,有很多的文章都描述瞭如何在Net Core下,模擬HttpContext.Current的。如:
等等文章。
但是它們都提到了需要在Startup類通過ioc注入東西,我的項目只是一個類庫,他可以運行在任何環境下,我該如何在類庫中使用HttpContext,並且我不想更改代碼。搜索了國內和國外的網站,都沒有一個很好的方案。我自己琢磨了一個臨時的方案:
- 在Nuget引用Microsoft.AspNetCore.Http庫,這是net core中HttpContextBase的庫
- 在我的新項目類頂級命名空間下,創建一個靜態類叫HttpContext,裏面具有一個Current的屬性,返回NetCore中的HttpContext,代碼如下:
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Text;
namespace Beyondbit.Framework
{
public class HttpContext
{
private static IHttpContextAccessor _accessor;
public static Microsoft.AspNetCore.Http.HttpContext Current => _accessor.HttpContext;
public static void Configure(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
}
}
- 修改代碼將System.Web.HttpContext.Current這樣的代碼改成 HttpContext.Current並引用System.Web命名空間
- 這樣同樣的代碼即可在老項目編譯通過,同時新項目也能編譯通過
- 目前這樣是可以編譯通過,但是 HttpContext.Current是null. 需要在 mvc core項目中的Startup類中,調用一下Beyondbit.Framework.HttpContext.Configure()方法,將httpConetxt的注入到類庫中
HttpContext.Current.Session問題
Net Core中的Session類和Net Framework的類變動非常的大,而且接口都已經變更,比如在Net Framework中HttpContext.Current.Session["Key"] 來獲取一個object類型的變量,但是在Net Core中這樣是不行的,Session已經不支持[]的寫法,HttpContext.Current.Session.TryGetValue,或者擴展方法HttpContext.Current.Session.Get,但這個接口默認返回的是byte[]類型,或者HttpContext.Current.Session.GetString這樣的方法獲取。
這樣的代碼已經和Net Framework無法兼容。
目前無奈的做法是:
- 修改代碼去除session的讀取,這個需要根據具體功能來調整,不能一概去除,要不然影響原來的功能
- 通過條件編譯,來使得net core項目不支持這些功能,而老項目編譯時依然支持, 在新項目中添加條件編譯的標誌NETSTANDARD2_0,然後典型的代碼如下:
if (HttpContext.Current == null)
return "";
#if NETSTANDARD2_0
throw new NotSupportedException();
#else
return HttpContext.Current.Session.SessionID;
#endif
NotSupportedException類是我添加的一個異常類,用來在遇到我們想項目時調用了一些我們臨時去掉的功能,可以很明顯告訴我們代碼的問題在哪裏
SqlCommandBuilder
目前這個類只能利用條件編譯先解決。
編譯結果已經全部OK了,可以看到我的編譯結果
總結:
第二步的工作是來消滅錯誤,目前已經全部完成,第三步是遷移單元測試和集成測試項目,以及最終的多個平臺運行的測試。