Category Archives: .NET

SqlBulkCopy 載入資料的資料精準度錯誤

小心

https://forums.asp.net/t/1300113.aspx?SqlBulkCopy+Precision+Error+from+C+Double+to+Sql+Decimal+

.NET 只有浮點數(single/double),並不支援 SQL Server 的 Numeric/Decimal 或 Oracle 的 Number,當使用 SqlBulkCopy 載入資料到 SQL Server 的目的欄位型別為 Numeric/Decimal 有指定小數位數十,可能發生轉換時,精準度差最小位數。

以上述的連結範例而言 27.2 放到 Numeric(10,4) 會造成 27.1999,若放到 Numeric(10,5),則是 27.19999。

可以採用如提問者自己在下方的解法,先存到中介 table,對應欄位宣告成 float,對應 .NET 使用的 double,然後再從中介轉到真正的目標 table,這時 float 轉 numeric,則數值就會正確。

廣告

當過濾欄位是 char/varchar 時,透過 SqlCommand 搭配 SqlParameter 時,大量存取會有效能考量

最近幫朋友壓測時,發現的問題。

依據 SQL Server 的 Data Type Precedence https://msdn.microsoft.com/en-us/library/ms190309.aspx

  1. user-defined data types (highest)
  2. sql_varian t
  3. xml
  4. datetimeoffset
  5. datetime2
  6. datetime
  7. smalldatetime
  8. date
  9. time
  10. float
  11. real
  12. decimal
  13. money
  14. smallmoney
  15. bigint
  16. int
  17. smallint
  18. tinyint
  19. bit
  20. ntext
  21. text
  22. image
  23. timestamp
  24. uniqueidentifier
  25. nvarchar (including nvarchar(max) )
  26. nchar
  27. varchar (including varchar(max) )
  28. char
  29. varbinary (including varbinary(max) )
  30. binary (lowest)

代表輸入的條件參數若是 unicode,而目標欄位是 char/varchr/text,將會是欄位內所有的紀錄值先轉型成 unicode,再跟輸入條件比較。

範例程式碼:

use tempdb

drop table if exists t1

create table t1(c1 int identity primary key,c2 char(6),c3 char(10),c4 varchar(50),c5 datetime2(7) default(sysdatetime()),
c6 uniqueidentifier default(newsequentialid()),c7 bigint default(0))

set nocount on

declare @i int=0
while @i<100000
begin
insert t1(c2,c3,c4) values(right(‘000000’+convert(varchar(6),@i),6),
right(‘0000000000’+convert(varchar(6),@i),10),rand())
set @i+=1
end

select * from t1

create index idx on t1(c2,c3,c4)
go
create proc sp @c2 char(6),@c3 char(10),@c4 varchar(50)
as
select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4
go

簡單利用 console 程式測試

using System;
using System.Data.SqlClient;

namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
using (SqlConnection cnn = new SqlConnection(“Data Source=.;Initial Catalog=tempdb;integrated security=sspi"))
{
SqlCommand cmd = new SqlCommand(“select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4″);
                cmd.Parameters.Add(new SqlParameter(“c2″, “000000″));
cmd.Parameters.Add(new SqlParameter(“c3″, “0000000000″));
cmd.Parameters.Add(new SqlParameter(“c4″, “0.0558658″));
                cmd.Connection = cnn;

SqlCommand cmd2 = new SqlCommand(“select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4″);
                cmd2.Parameters.Add(new SqlParameter(“c2″, System.Data.SqlDbType.Char,6));
cmd2.Parameters.Add(new SqlParameter(“c3″, System.Data.SqlDbType.Char, 10));
cmd2.Parameters.Add(new SqlParameter(“c4″, System.Data.SqlDbType.VarChar, 50));
                cmd2.Parameters[0].Value = “000000″;
cmd2.Parameters[1].Value = “0000000000″;
cmd2.Parameters[2].Value = “0.0558658″;
cmd2.Connection = cnn;

SqlCommand cmd3 = new SqlCommand(“sp");
cmd3.CommandType = System.Data.CommandType.StoredProcedure;
cmd3.Parameters.Add(new SqlParameter(“c2″, “000000″));
cmd3.Parameters.Add(new SqlParameter(“c3″, “0000000000″));
cmd3.Parameters.Add(new SqlParameter(“c4″, “0.0558658″));
cmd3.Connection = cnn;

cnn.Open();
long l = DateTime.Now.Ticks;
int times = 100000;
for(int i=0;i<times;i++)
{
//exec sp_executesql N’select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4′,N’@c2 nvarchar(6),@c3 nvarchar(10),@c4 nvarchar(9)’,@c2=N’000000′,@c3=N’0000000000′,@c4=N’0.0558658′
SqlDataReader dr = cmd.ExecuteReader();
dr.Close();
}
Console.WriteLine((DateTime.Now.Ticks – l).ToString());

System.Threading.Thread.Sleep(3000);

l = DateTime.Now.Ticks;
for (int i = 0; i <times; i++)
{
//exec sp_executesql N’select c1 from t1 where c2=@c2 and c3=@c3 and c4=@c4′,N’@c2 char(6),@c3 char(10),@c4 varchar(50)’,@c2=’000000′,@c3=’0000000000′,@c4=’0.0558658′
SqlDataReader dr = cmd2.ExecuteReader();
dr.Close();
}
Console.WriteLine((DateTime.Now.Ticks – l).ToString());
System.Threading.Thread.Sleep(3000);

l = DateTime.Now.Ticks;
for (int i = 0; i < times; i++)
{
//exec sp @c2=N’000000′,@c3=N’0000000000′,@c4=N’0.0558658′
SqlDataReader dr = cmd3.ExecuteReader();
dr.Close();
}
Console.WriteLine((DateTime.Now.Ticks – l).ToString());
}
}
}
}

 

若 .NET 未指定 type,會自動賦予 nvarchar,導致欄位為 char 的要轉成 nvarchar 再行比較,以此例而言,也就是每次比較就需要轉 10 萬筆,3 欄位的紀錄值:

image

就單次查詢時,SQL Server 的執行計畫判讀不覺得有效能差,所以彼此占比相同。

但重複執行 10 萬次後,時間上,可以看得出來,因為指定正確的欄位型態,或是 Stored Procedure 只需要輸入參數時轉對參數型態,實際語法比較時,不需逐筆轉換,所以效率較佳。

image

就總 CPU 耗用而言,因為無法平行運算,轉資料型態導致 CPU 要跑得比較久,但只會操死一顆 CPU

image

調整 Visual Studio 語言

為了安裝 SSDT 2015 August CTP(14.0.50901.0),https://msdn.microsoft.com/zh-tw/mt429383,這對應的是 SQL Server 2016 CTP 2.3

好在 TechDay Demo SSIS 透過 .NET Framework 4.6 可以存取 Always Encrypted DB,但當下只有英文版,而我的 VS 2015 裝的是中文版,因此預設無法安裝這個 SSDT

更改 VS 2015 的語言,透過 控制台 –> 程式和功能 –>  變更

image

從網站下載 Visual Studio 2015 English Language Pack 安裝

http://www.microsoft.com/en-US/download/details.aspx?id=48157

image

裝了 Language Pack 後就可以安裝了 SSDT 2015

image

可以在 Visual Studio 的選項內更改語言

image

在 VS 2015 開 SSIS 2016 CTP 2.3 的專案,可惜尚看不到什麼大變動…

image

透過 .NET Framework 4.6 提供的 SQLClient 存取 SQL Server 2016 CTP 2.3 提供的 Always Encrypted 資料

image

簡單透過 Column Encryption Setting 連接設定在 SSIS 檢視 Always Encrypted 解密後的資料

image

VS 2013 Update 4 造成 Web Template 損毀

狀況:

image

確定後的錯誤訊息

image

透過控制台修復

image

image

修復後就正常了

參考: http://stackoverflow.com/questions/26955822/visual-studio-2013-update-4-has-broken-web-templates

Visual Studio Release Management 的 Debug 方式

參考:http://blogs.msdn.com/b/visualstudioalm/archive/2013/12/13/how-to-enable-detailed-logs-and-collect-traces-from-various-release-management-components.aspx

DeploymentAgent.exe 要停掉的 Windows 服務是 Microsoft Deployment Agent,否則無法修改 .config 檔案

Team Build Error

機器上只裝了 VS 2013+TFS 2013,透過 Team Build 組建舊的微軟範例會失敗,可能是因為我用了 Release Management 的 C:\Program Files (x86)\Microsoft Visual Studio 12.0\Release Management\bin\ReleaseDefaultTemplate.11.1.xaml 發行範本,而它指定用 MSBuild 11…

C:\Builds\1\myTeamProject\FabrikamFiber.CallCenter\Sources\FabrikamFiber.CallCenter\FabrikamFiber.Web\FabrikamFiber.Web.csproj (336): 找不到匯入的專案 “C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets"。請確認 <Import> 宣告中的路徑正確,而且檔案存在於磁碟上。

image

需要將舊版安裝於以下目錄的內容:

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0

之 WebApplications 子目錄 Copy 到當下安裝的相同位置即可

參考:http://stackoverflow.com/questions/17433904/v11-0-webapplications-microsoft-webapplication-targets-was-not-found-when-file-a

VS Release Management 2013 升級到 Update 3

參照這個網頁的作法:http://msdn.microsoft.com/zh-tw/library/dn593704.aspx

移除既有的 Release Management Server 和 Client 後重新安裝 Update 3 的版本

透過 C:\Program Files (x86)\Microsoft Visual Studio 12.0\Release Management\bin\ReleaseConfigurationUI.exe 指定回原 RM 的 SQL Server 資料庫後即可:

image

Web Service 透過 trace.axd 觀察執行狀況

HttpContext.Current.Trace.Write

http://forums.asp.net/t/1099533.aspx?Debug+Tracing+in+a+Web+Service

與 TFS 相關,各種不同用途的工具

感謝 Dann 提供的連結 Visual Studio ALM Community Widgets http://blogs.msdn.com/b/willy-peter_schaub/archive/2014/06/19/visual-studio-alm-community-widgets-aka-ms-widgets.aspx

Release Management 和 SharePoint 裝在同一台會有問題

感謝 Cary Hsu 提供的解法:

http://www.colinsalmcorner.com/post/fix-release-management-service-unavailable-503

http://myalmblog.com/2014/03/01/error-installing-release-management-client/

若安裝的當下無法設定 RM(例如上述問題導致安裝成功但因 Services 起不來而無法設定),事後要修改,則可以到以下路徑執行相關的程式

  • RM Services 可利用"開始"目錄內 “Microsoft Visual Studio Team Foundation Server 2013″ 之下的 “Team Foundation Server 2013 Release Management 伺服器",實際檔案位置:C:\Program Files (x86)\Microsoft Visual Studio 12.0\Release Management\bin\ReleaseConfigurationUI.exe
  • RM Client 可利用"開始"目錄內 “Visual Studio 2013″ 之下的 “Visual Studio 2013 Release Management 用戶端",實際檔案位置:C:\Program Files (x86)\Microsoft Visual Studio 12.0\Release Management\Client\bin\ReleaseManagementConsole.exe
  • Agent 要利用 C:\Program Files (x86)\Microsoft Visual Studio 12.0\Release Management\bin\DeploymentAgentConfigUI.exe

在以下這個 MVA 有談到安裝,以及這個問題

http://www.microsoftvirtualacademy.com/Content/ViewContent.aspx?et=8379&m=8374&ct=28411