C# BulkCopy.WriteToServer 更改值
C# BulkCopy.WriteToServer Changing Values
我有一个从 excel sheet 创建的数据表。我正在尝试 SqlBulkCopy.WriteToServer。当我这样做时,当我的表架构的 "Percent" 列的类型为 Decimal(38,0) 时,它会将我的 "Percent" 值转换为 0。但是,当我将数据类型设置为 Float 时,它会正确插入。我不确定发生了什么。如果可能的话,我想使用 Decimal(38, 0),因为我得到的价差 sheet 可能超过 15 个小数位。
数据表的所有列都是字符串类型,因为我可能必须处理空值。
这是我的 C# 代码:
private bool ImportToDataBase(DataTable emeTable)
{
string serverName = PARR_DBDataObject.ServerName;
string dbName = PARR_DBDataObject.DBName;
bool dataUploaded = false;
using ( SqlConnection conn = SQL.ConnectToDB(dbName, serverName, false))
{
conn.Open();
string createTempTable = $@"CREATE TABLE #Holdings(
[Fund][varchar](25) NULL,
[Percent] [varchar](38) NULL,
[Committed] [varchar](25) NULL,
[DryPowder] [varchar](25) NULL,
[CashBalance] [varchar](25) NULL,
[Trades] [varchar](25) NULL,
[Capital] [varchar](25) NULL,
[MgmtFee] [varchar](25) NULL,
[Cash] [varchar](25) NULL,
[ReportDate] [datetime] NULL);";
SqlCommand cmd = new SqlCommand(createTempTable, conn);
cmd.ExecuteNonQuery();
using(SqlBulkCopy blkCopy = new SqlBulkCopy(conn))
{
decimal test = Convert.ToDecimal(emeTable.Rows[0][1]);
foreach(DataColumn col in emeTable.Columns)
{
blkCopy.ColumnMappings.Add(col.Ordinal, col.Ordinal);
}
blkCopy.DestinationTableName = "#Holdings";
blkCopy.WriteToServer(emeTable);
string sqlSelect = "SELECT * FROM #Holdings";
SqlCommand emeCmd = new SqlCommand(sqlSelect, conn);
SqlDataAdapter da = new SqlDataAdapter(emeCmd);
DataTable testTable = new DataTable();
da.Fill(testTable);
da.Dispose();
}
string spName = DBDataObject.sp_Insert_Into_CashHoldings;
SqlCommand cmdSP = new SqlCommand(spName, conn);
cmdSP.ExecuteNonQuery();
//SQL.NonQueryStoredProcedure(spName, dbName, serverName, false, 600);
dataUploaded = true;
}
return dataUploaded;
}
这是我的 SQL 从 Temp Table 获取数据并进入主 Table:
ALTER PROCEDURE [dbo].[sp_Insert_Into_CashHoldings]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
MERGE t_CashHoldings AS TARGET
USING #Holdings AS SOURCE
ON (TARGET.Fund = SOURCE.Fund AND TARGET.ReportDate= SOURCE.ReportDate)
WHEN MATCHED THEN
UPDATE SET TARGET.Percent = SOURCE.Percent,
TARGET.Committed = SOURCE.Committed,
TARGET.DryPowder = SOURCE.DryPowder,
TARGET.Trades = SOURCE.Trades,
TARGET.Capital = SOURCE.Capital,
TARGET.MgmtFee = SOURCE.MgmtFee,
TARGET.Cash = SOURCE.Cash
WHEN NOT MATCHED THEN
INSERT (Fund, Percent, Committed, DryPowder, CashBalance, Trades, Capital, MgmtFee, Cash, ReportDate)
VALUES (SOURCE.Fund, SOURCE.Percent, SOURCE.Committed, SOURCE.DryPowder, SOURCE.CashBalance, SOURCE.Trades, SOURCE.Capital,
SOURCE.MgmtFee, SOURCE.Cash, SOURCE.ReportDate);
DROP TABLE #Holdings;
END
如果这是错误的答案,我可以将其删除 - 但如果您执行 decimal(38,0) 这表示您想要一个 # 在小数点左侧有 38 位并允许在右侧有 0 .你会想要像 38,10 这样的东西,这意味着总共 38 个数字,但左边 28 个,右边 10 个。如果您的值存储为 0.56,那么这可能就是它被切断的原因。
话虽如此,我建议做一些像 28,10 这样的事情,因为 .NET 最多只支持 28 位精度,而 sql 服务器的精度是 38 位。如果您尝试将像这样的大 # 引入 .NET稍后,它会崩溃。
希望对您有所帮助!
我有一个从 excel sheet 创建的数据表。我正在尝试 SqlBulkCopy.WriteToServer。当我这样做时,当我的表架构的 "Percent" 列的类型为 Decimal(38,0) 时,它会将我的 "Percent" 值转换为 0。但是,当我将数据类型设置为 Float 时,它会正确插入。我不确定发生了什么。如果可能的话,我想使用 Decimal(38, 0),因为我得到的价差 sheet 可能超过 15 个小数位。
数据表的所有列都是字符串类型,因为我可能必须处理空值。
这是我的 C# 代码:
private bool ImportToDataBase(DataTable emeTable)
{
string serverName = PARR_DBDataObject.ServerName;
string dbName = PARR_DBDataObject.DBName;
bool dataUploaded = false;
using ( SqlConnection conn = SQL.ConnectToDB(dbName, serverName, false))
{
conn.Open();
string createTempTable = $@"CREATE TABLE #Holdings(
[Fund][varchar](25) NULL,
[Percent] [varchar](38) NULL,
[Committed] [varchar](25) NULL,
[DryPowder] [varchar](25) NULL,
[CashBalance] [varchar](25) NULL,
[Trades] [varchar](25) NULL,
[Capital] [varchar](25) NULL,
[MgmtFee] [varchar](25) NULL,
[Cash] [varchar](25) NULL,
[ReportDate] [datetime] NULL);";
SqlCommand cmd = new SqlCommand(createTempTable, conn);
cmd.ExecuteNonQuery();
using(SqlBulkCopy blkCopy = new SqlBulkCopy(conn))
{
decimal test = Convert.ToDecimal(emeTable.Rows[0][1]);
foreach(DataColumn col in emeTable.Columns)
{
blkCopy.ColumnMappings.Add(col.Ordinal, col.Ordinal);
}
blkCopy.DestinationTableName = "#Holdings";
blkCopy.WriteToServer(emeTable);
string sqlSelect = "SELECT * FROM #Holdings";
SqlCommand emeCmd = new SqlCommand(sqlSelect, conn);
SqlDataAdapter da = new SqlDataAdapter(emeCmd);
DataTable testTable = new DataTable();
da.Fill(testTable);
da.Dispose();
}
string spName = DBDataObject.sp_Insert_Into_CashHoldings;
SqlCommand cmdSP = new SqlCommand(spName, conn);
cmdSP.ExecuteNonQuery();
//SQL.NonQueryStoredProcedure(spName, dbName, serverName, false, 600);
dataUploaded = true;
}
return dataUploaded;
}
这是我的 SQL 从 Temp Table 获取数据并进入主 Table:
ALTER PROCEDURE [dbo].[sp_Insert_Into_CashHoldings]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
MERGE t_CashHoldings AS TARGET
USING #Holdings AS SOURCE
ON (TARGET.Fund = SOURCE.Fund AND TARGET.ReportDate= SOURCE.ReportDate)
WHEN MATCHED THEN
UPDATE SET TARGET.Percent = SOURCE.Percent,
TARGET.Committed = SOURCE.Committed,
TARGET.DryPowder = SOURCE.DryPowder,
TARGET.Trades = SOURCE.Trades,
TARGET.Capital = SOURCE.Capital,
TARGET.MgmtFee = SOURCE.MgmtFee,
TARGET.Cash = SOURCE.Cash
WHEN NOT MATCHED THEN
INSERT (Fund, Percent, Committed, DryPowder, CashBalance, Trades, Capital, MgmtFee, Cash, ReportDate)
VALUES (SOURCE.Fund, SOURCE.Percent, SOURCE.Committed, SOURCE.DryPowder, SOURCE.CashBalance, SOURCE.Trades, SOURCE.Capital,
SOURCE.MgmtFee, SOURCE.Cash, SOURCE.ReportDate);
DROP TABLE #Holdings;
END
如果这是错误的答案,我可以将其删除 - 但如果您执行 decimal(38,0) 这表示您想要一个 # 在小数点左侧有 38 位并允许在右侧有 0 .你会想要像 38,10 这样的东西,这意味着总共 38 个数字,但左边 28 个,右边 10 个。如果您的值存储为 0.56,那么这可能就是它被切断的原因。
话虽如此,我建议做一些像 28,10 这样的事情,因为 .NET 最多只支持 28 位精度,而 sql 服务器的精度是 38 位。如果您尝试将像这样的大 # 引入 .NET稍后,它会崩溃。
希望对您有所帮助!