实体框架中的用户定义表生成了错误的查询


10

我认为我目前在Entity Framework 6中以及可能在ADO.NET中遇到错误。由于有最后期限,所以我不确定是否可以等待此错误被修复,希望有人可以帮助我进行整洁的工作。

问题是查询在应为0.01和0.05的位置使用值1和5。但是奇怪的是0.1似乎可以正常工作

当前生成的查询是:(从SQL Server Profiler获取)

declare @p3  dbo.someUDT
insert into @p3 values(NULL,5)
insert into @p3 values(5,0.10)
insert into @p3 values(NULL,1)
insert into @p3 values(1,2)

exec sp_executesql N'Select * from @AName',N'@AName  [dbo].[someUDT] READONLY',@AName=@p3

正确的代码是:

declare @p3  dbo.someUDT
insert into @p3 values(NULL,0.05)
insert into @p3 values(0.05,0.10)
insert into @p3 values(NULL,0.01)
insert into @p3 values(0.01,0.02)

exec sp_executesql N'Select * from @AName',N'@AName  [dbo].[someUDT] READONLY',@AName=@p3

我已经在github上创建了一个问题:用户定义的表插入了错误的值

我想在参数化查询中使用用户定义的表,此问题说明了如何完成此操作: 实体框架存储过程表值参数

这是用于获取上述SQL代码的C#代码

DataTable dataTable = new DataTable();
dataTable.Columns.Add("value1", typeof(decimal));
dataTable.Columns.Add("value2", typeof(decimal));

dataTable.Rows.Add(null,0.05m); 
dataTable.Rows.Add(0.05m,0.1m); 
dataTable.Rows.Add(null,0.01m); 
dataTable.Rows.Add(0.01m,0.02m); 
List<SqlParameter> Parameters = new List<SqlParameter>();

Parameters.Add(new SqlParameter("@AName", SqlDbType.Structured) { Value = dataTable , TypeName= "dbo.someUDT" });

dbContext.Database.ExecuteSqlCommand("Select * from @AName", Parameters.ToArray());

和SQL代码获取用户定义表

CREATE TYPE [dbo].[someUDT] AS TABLE
(
   [value1] [decimal](16, 5) NULL,
   [value2] [decimal](16, 5) NULL
)

编辑:
Gert Arnold弄清楚了。根据他的回答,我在这里找到了一个现有报告SQL Server Profiler TextData Column处理了不正确的十进制输入


2
你可以试试这个dataTable.Rows.Add(null,0.05m); 和检查什么查询它产生
rjs123431

1
@ rjs123431我之前尝试过,它给出相同的结果
Joost K,

1
您要创建一个新表并返回该表的所有值吗?抱歉,但我不明白您真正想要的是什么。您能分享一下您的主要目标吗?
Lutti Coelho

1
@LuttiCoelho很抱歉给您带来的困惑,Select * from @AName是作为占位符。我实际上是在表中加入一个更大的查询,我认为该查询与该问题无关,因为这已经以一种更简单的格式复制了该问题。
Joost K

2
奇怪的是,我确实看到了不正确的SQL,但是当我使用Database.SqlQuery(而不是Database.ExecuteSqlCommand)时,会在客户端中收到正确的值!
Gert Arnold

Answers:


11

这是一个奇怪的Sql Profiler工件。值已正确传输。我可以通过使用用户定义的类型和一个小表创建数据库来证明这一点:

CREATE TABLE [dbo].[Values](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Value] [decimal](16, 5) NOT NULL,
 CONSTRAINT [PK_Values] PRIMARY KEY CLUSTERED ([Id] ASC) ON [PRIMARY]
GO

并插入几个值:

Id          Value
----------- ---------------------------------------
1           10.00000
2           1.00000
3           0.10000
4           0.01000

然后我运行您的代码,稍作修改:

DataTable dataTable = new DataTable();
dataTable.Columns.Add("value1", typeof(decimal));
dataTable.Columns.Add("value2", typeof(decimal));

dataTable.Rows.Add(0.001m, 0.03m);
List<SqlParameter> Parameters = new List<SqlParameter>();

Parameters.Add(new SqlParameter("@AName", SqlDbType.Structured) { Value = dataTable, TypeName = "dbo.someUDT" });

using(var context = new MyContext(connStr))
{
    var query = "Select v.Id from dbo.[Values] v, @AName a "
        + " where v.Value BETWEEN a.value1 AND a.value2";
    var result = context.Database.SqlQuery<int>(query, Parameters.ToArray());
}

MyContex只是一个继承自DbContext其他)

之间只有一个值0.001m0.03m 而这恰恰是查询返回的内容4

但是,Sql Server事件探查器记录以下内容:

declare @p3 dbo.someUDT
insert into @p3 values(1,3) -- See here: the log is warped

exec sp_executesql N'Select v.Value from dbo.[Values] v, @AName a  where v.Value BETWEEN a.value1 AND a.value2',N'@AName [dbo].[someUDT] READONLY',@AName=@p3

在SSMS中返回记录#2。

我认为这与区域设置和十进制分隔符与日志记录中某处的十进制组分隔符混淆有关。


1
我从没想过这个问题在日志记录中。开箱即用的思维很棒,谢谢您解决这个问题!
Joost K,

2
根据您的回答,我得到了该错误报告feedback.azure.com/forums/908035-sql-server/suggestions / ...似乎我并不是唯一的一个。
Joost K

1

老实说,我和您有不同的问题:

这是我的探查器日志:

declare @p3 dbo.someUDT
insert into @p3 values(NULL,0.05)
insert into @p3 values(0.05,0.10)
insert into @p3 values(NULL,0.01)
insert into @p3 values(0.01,0.02)

exec sp_executesql N'Select * from @AName',N'@AName [dbo].[someUDT] READONLY',@AName=@p3

我尝试了EntityFramework版本6.2.0&6.3.0&6.4.0,但这些都没有显示问题:

DataTable dataTable = new DataTable();
dataTable.Columns.Add("value1", typeof(decimal));
dataTable.Columns.Add("value2", typeof(decimal));

dataTable.Rows.Add(null, 0.05);
dataTable.Rows.Add(0.05M, 0.1M);
dataTable.Rows.Add(null, 0.01);
dataTable.Rows.Add(0.01, 0.02);
List<SqlParameter> Parameters = new List<SqlParameter>();

Parameters.Add(new SqlParameter("@AName", SqlDbType.Structured) { Value = dataTable, TypeName = "dbo.someUDT" });

var dbContext = new test01Entities();
dbContext.Database.ExecuteSqlCommand("Select * from @AName", Parameters.ToArray());

另外,我测试ADO.NET并得到相同的结果:

SqlConnection cn = new SqlConnection("Data Source=(local);Initial Catalog=Test01;Integrated Security=true;");
using (var cmd = new SqlCommand("[foo]", cn))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cn.Open();
    cmd.Parameters.AddWithValue("@param1", 0.02);
    cmd.Parameters.AddWithValue("@param2", 0.020);
    cmd.ExecuteNonQuery();
}

我正在使用Visual Studio 2017,.NET Framework 4.6.1和Microsoft SQL Server Enterprise(64位)


4
我很确定这与语言设置(计算机还是数据库)有关,所以您很幸运。
Gert Arnold

2
我必须补充一点,我和@GertArnold都生活在同一个国家,这很可能解释了我们俩都可以重现此问题的原因
Joost K

2
@GertArnold请制作示例(VS解决方案+ SQL数据库)并共享。我会找到线索的。
XAMT

1
@XAMT这是Sql Server Profiler的一个错误,因此我们无法控制。如果愿意,您可以使用计算机和数据库服务器的语言设置来查看在运行代码时何时出现错误,但是IMO在消遣部门中。
Gert Arnold
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.