將 Net 項目升級 Core項目經驗:(二)修復遷移後Net Standard項目中的錯誤

修復遷移後Net Standard項目中的錯誤

接上一章,項目編譯結果如下:
image

解決依賴dll引用

在Net Framework項目的引用如下:
image

各引用和作用:

  • 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的其他的都不支持。

新項目的引用截圖:
image

數據庫相關的錯誤修訂

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環境下,會讀取一些以前特定的代碼,這個問題是最難處理的。如以下代碼:
image
可以看到編譯提示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無法兼容。

目前無奈的做法是:

  1. 修改代碼去除session的讀取,這個需要根據具體功能來調整,不能一概去除,要不然影響原來的功能
  2. 通過條件編譯,來使得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了,可以看到我的編譯結果

image

總結
第二步的工作是來消滅錯誤,目前已經全部完成,第三步是遷移單元測試和集成測試項目,以及最終的多個平臺運行的測試。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章