我们使用的是.net Framework 4.7.2。 我们调用一个 SP,将用户定义的类型变量作为其唯一参数。
CREATE TYPE [dbo].[ABC] AS TABLE(
[A] [int] NOT NULL,
[B] [datetime] NOT NULL,
[C] [datetime] NOT NULL,
[Value] [decimal](19, 6) NULL)
对应的存储过程为
CREATE PROCEDURE [dbo].[myUSP]
@data dbo.ABC readonly AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (SELECT 1 FROM @data)
BEGIN
INSERT INTO dbo.MyTable
SELECT A, B, C, [Value] FROM @data;
END END
我的 .Net 代码是
using (SqlConnection con = new SqlConnection(connectionString))
{
using (SqlCommand insertCmd = new SqlCommand("dbo.myUSP", con))
{
con.Open();
using (transaction = con.BeginTransaction(IsolationLevel.RepeatableRead))
{
insertCmd.Transaction = transaction;
insertCmd.CommandType = CommandType.StoredProcedure;
try
{
SqlParameter parameter1 = insertCmd.Parameters.AddWithValue("@data", CreateSqlRecord(insert));
parameter1.SqlDbType = SqlDbType.Structured;
parameter1.TypeName = "dbo.ABC";
insertCmd.ExecuteNonQuery();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
}
}
}
}
private IEnumerable<SqlDataRecord> CreateSqlRecord(IEnumerable<DataElementInput> entities)
{
SqlMetaData[] metaData = new SqlMetaData[4];
metaData[0] = new SqlMetaData("A", SqlDbType.Int);
metaData[1] = new SqlMetaData("B", SqlDbType.DateTime);
metaData[2] = new SqlMetaData("C", SqlDbType.DateTime);
metaData[3] = new SqlMetaData("Value", SqlDbType.Decimal);
SqlDataRecord record = new SqlDataRecord(metaData);
foreach (Model myModel in entities)
{
record.SetInt32(0, myModel .A);
record.SetDateTime(1,myModel.B);
record.SetDateTime(2, myModel.C);
record.SetDecimal(3, (Decimal)myModel.Value);
yield return record;
}
}
我检查了参数 1 的值,因为它被传递给 SQLConnection 并使用 ExecuteNonQuery 执行,它正确地包含十进制值。 另一方面,我还检查了直接从 SQL 服务器管理工作室运行我的 sp,它在表 dbo 中插入正确的十进制值。我的表。
BEGIN DECLARE @data dbo.ElementFactData;INSERT @data (ElementId,StartDateTime, EndDateTime, Value) VALUES( 1002, '1/1/1800' , '1/1/1900' , 0.786); exec dbo.myUSP @data;END
但是,当我尝试从 .net 代码插入记录时,小于 0.5 的十进制值变为 0,高于 0.5 的值变为 1。像 4.2 变成 4,5.87 变成 6
我的 .net 代码有什么问题吗?
我猜
metaData[3] = new SqlMetaData("Value", SqlDbType.Decimal);
需要以精度和小数位数指定。 所以它看起来像这样:
metaData[3] = new SqlMetaData("Value", SqlDbType.Decimal, 19, 6);
您的 CreateSqlRecord 方法应如下所示:
private IEnumerable<SqlDataRecord> CreateSqlRecord(IEnumerable<DataElementInput> entities)
{
SqlMetaData[] metaData = new SqlMetaData[4];
metaData[0] = new SqlMetaData("A", SqlDbType.Int);
metaData[1] = new SqlMetaData("B", SqlDbType.DateTime);
metaData[2] = new SqlMetaData("C", SqlDbType.DateTime);
metaData[3] = new SqlMetaData("Value", SqlDbType.Decimal, 19, 6);
SqlDataRecord record = new SqlDataRecord(metaData);
foreach (Model myModel in entities)
{
record.SetInt32(0, myModel .A);
record.SetDateTime(1,myModel.B);
record.SetDateTime(2, myModel.C);
record.SetDecimal(3, (Decimal)myModel.Value);
yield return record;
}
}