잘못된 쿼리를 생성하는 Entity Framework의 사용자 정의 테이블


10

나는 현재 Entity Framework 6 및 ADO.NET에 버그가 있다고 생각합니다. 마감 기한이 있기 때문에이 버그가 수정 될 때까지 기다릴 수 있으며 누군가가 깨끗한 작업을 도와 줄 수 있기를 바랍니다.

문제는 쿼리가 0.01과 0.05 여야하는 위치에서 값 1과 5를 사용한다는 것입니다. 그러나 이상하게도 0.1이 작동하는 것 같습니다

생성 된 쿼리는 현재 다음과 같습니다. (SQL Server 프로파일 러에서 가져옴)

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에서 이미 문제를 만들었습니다. 잘못된 값을 삽입하는 사용자 정의 테이블

매개 변수가 지정된 쿼리에서 사용자 정의 테이블을 사용하고 싶습니다.이 질문은이 작업이 수행되는 방법을 설명합니다. Entity Framework 저장 프로 시저 테이블 값 매개 변수

위의 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 프로파일 러 TextData 열은 소수 입력을 잘못 처리합니다.


2
당신이 시도 할 수 dataTable.Rows.Add(null,0.05m); 있으며 생성 어떤 쿼리 확인
rjs123431

1
@ rjs123431 나는 전에를 시도하고 같은 결과를 제공
주스 K를

1
새 테이블을 만들고 테이블의 모든 값을 반환 하시겠습니까? 죄송하지만, 당신이 정말로 원하는 것을 이해하지 못합니다. 이것의 주요 목표가 무엇인지 공유 할 수 있습니까?
Lutti Coelho

1
@LuttiCoelho 혼란을 드려 죄송합니다 Select * from @AName. 실제로 문제를 더 간단한 형식으로 복제하기 때문에 질문과 관련이 없다고 생각되는 더 큰 쿼리로 테이블에 참여하고 있습니다.
Joost K

2
이상한 것은 실제로 잘못된 SQL을 보는 것이지만 Database.SqlQuery(대신 Database.ExecuteSqlCommand)를 사용할 때 클라이언트에서 올바른 값을받습니다!
Gert Arnold

답변:


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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.