एंटिटी फ्रेमवर्क में उपयोगकर्ता परिभाषित तालिका गलत क्वेरी उत्पन्न करती है


10

मुझे लगता है कि मैं वर्तमान में Entity Framework 6 और संभवतः ADO.NET में बग का अनुभव कर रहा हूं। चूंकि एक समय सीमा है, मुझे यकीन नहीं है कि मैं इस बग को ठीक करने के लिए इंतजार कर सकता हूं और उम्मीद है कि कोई व्यक्ति मेरे चारों ओर साफ काम करने में मदद कर सकता है।

समस्या यह है कि क्वेरी उन स्थानों पर मान 1 और 5 का उपयोग करती है जहां यह 0.01 और 0.05 होना चाहिए। हालाँकि विचित्र रूप से पर्याप्त 0.1 काम कर रहा है

वर्तमान में उत्पन्न क्वेरी है: (SQL सर्वर प्रोफाइलर से प्राप्त)

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 पर एक मुद्दा बनाया है: उपयोगकर्ता परिभाषित तालिका गलत मान सम्मिलित करती है

मैं अपनी पैरामीटर क्वेरी में उपयोगकर्ता परिभाषित तालिका का उपयोग करना चाहता हूं, यह प्रश्न बताता है कि यह कैसे किया जाता है: एंटिटी फ्रेमवर्क संग्रहीत प्रक्रिया प्रक्रिया मूल्य मान पैरामीटर

यह C # कोड है जिसका उपयोग SQL कोड को ऊपर लाने के लिए किया जाता है

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
)

संपादित करें:
गर्ट अर्नोल्ड ने यह पता लगाया। उनके जवाब के आधार पर मुझे एक मौजूदा रिपोर्ट मिली जिसमें SQL Server Profiler TextData Column गलत तरीके से Decimal Input को हैंडल करता है


2
क्या आप इसे आज़मा सकते हैं dataTable.Rows.Add(null,0.05m); और जाँच सकते हैं कि यह किस क्वेरी को उत्पन्न करता है
rjs123431

1
@ rjs123431 मैंने कोशिश की कि पहले और यह एक ही परिणाम देता है
Joost K

1
आप एक नई तालिका बनाना चाहते हैं और तालिका के सभी मूल्यों को वापस करना चाहते हैं? क्षमा करें, लेकिन मुझे समझ में नहीं आता कि आप वास्तव में क्या चाहते हैं। क्या आप इसके साथ अपना प्रमुख लक्ष्य साझा कर सकते हैं?
लुट्टी कुल्हो

1
@LuttiCoelho भ्रम के लिए खेद है, Select * from @ANameप्लेसहोल्डर के रूप में है। मैं वास्तव में एक बड़ी क्वेरी में टेबल पर शामिल हो रहा हूं जो मुझे नहीं लगा कि यह सवाल प्रासंगिक था क्योंकि यह पहले से ही एक सरल प्रारूप में मुद्दे की नकल करता है।
जोस्ट के

2
अजीब बात है, मैं वास्तव में गलत एसक्यूएल देखता हूं, लेकिन जब मैं उपयोग करता हूं Database.SqlQuery(इसके बजाय Database.ExecuteSqlCommand) मैं क्लाइंट में सही मान प्राप्त करता हूं!
गर्ट अर्नोल्ड

जवाबों:


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.001mऔर 0.03m और कहा कि वास्तव में क्या क्वेरी है : 4

हालाँकि, Sql सर्वर प्रोफाइलर इसे लॉग करता है:

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
मैं इस मुद्दे पर लॉगिंग में होने के बारे में कभी नहीं सोचा था। बॉक्स से बाहर महान सोच और इसे हल करने के लिए धन्यवाद!
जोस्ट के

2
आपके उत्तर के आधार पर मुझे यह बग रिपोर्ट फ़ीडबैक मिली ।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 फ्रेमवर्क 4.6.1 और Microsoft SQL सर्वर एंटरप्राइज (64-बिट) का उपयोग कर रहा हूं


4
मुझे पूरा यकीन है कि यह भाषा सेटिंग (मशीन बनाम डेटाबेस) से संबंधित है, इसलिए आप सिर्फ भाग्यशाली हैं।
गर्ट अर्नाल्ड

2
मुझे यह जोड़ना है कि मेरे और @GertArold दोनों एक ही देश में रहते हैं जिससे एक बहुत ही संभावित व्याख्या हो सकती है कि हम दोनों समस्या को फिर से क्यों ला सकते हैं
Joost K

2
@GertArnold कृपया एक नमूना (VS समाधान + SQL डेटाबेस) बनाएं और इसे साझा करें। मुझे सुराग मिल जाएगा।
XAMT

1
@ XAMT यह एक Sql सर्वर प्रोफाइलर बग है इसलिए यह हमारे हाथ से बाहर है। यदि आप चाहें तो अपने मशीन और डेटाबेस सर्वर की भाषा सेटिंग्स के साथ खेल सकते हैं यह देखने के लिए कि जब आप अपना कोड चलाते हैं तो बग दिखाई देता है, लेकिन IMO वह है जो शगल विभाग में है।
गर्ट अर्नाल्ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.