সত্তা কাঠামোর নাল মানগুলির জন্য আমি কীভাবে জিজ্ঞাসা করতে পারি?


109

আমি এই জাতীয় একটি কোয়েরি কার্যকর করতে চাই

   var result = from entry in table
                     where entry.something == null
                     select entry;

এবং একটি IS NULLউত্পন্ন পেতে ।

সম্পাদিত: প্রথম দুটি উত্তরের পরে আমি স্পষ্ট করে বলার প্রয়োজন বোধ করছি যে আমি এসকিউএল-তে লিনক নয়, সত্তা ফ্রেমওয়ার্ক ব্যবহার করছি। অবজেক্ট.একুয়ালস () পদ্ধতিটি EF তে কাজ করে বলে মনে হচ্ছে না।

2 নং সম্পাদনা করুন: উপরোক্ত ক্যোয়ারী উদ্দেশ্য হিসাবে কাজ করে। এটি সঠিকভাবে উত্পন্ন করে IS NULL। আমার প্রোডাকশন কোডটি কিন্তু ছিল

value = null;
var result = from entry in table
                         where entry.something == value
                         select entry;

এবং উত্পন্ন এসকিউএল ছিল something = @p; @p = NULL। দেখে মনে হয় যে EF সঠিকভাবে ধ্রুবক ভাবটি অনুবাদ করে তবে কোনও ভেরিয়েবল জড়িত থাকলে এটি এটি একটি সাধারণ তুলনার মতোই আচরণ করে। আসলে জ্ঞান করে। আমি এই প্রশ্নটি বন্ধ করব


17
আমি মনে করি এটি সত্যিকার অর্থে বোঝায় না ... সংযোগকারীটি একটু স্মার্ট হওয়া উচিত এবং আমাদের এটির কাজটি করতে বলছে না: সঠিক সি # ক্যোয়ারির এসকিউএল-তে একটি সঠিক অনুবাদ সম্পাদন করুন। এটি একটি অপ্রত্যাশিত আচরণ উত্পন্ন করে।
জুলিয়েন এন

6
আমি জুলিয়েনের সাথে আছি, ইএফ
মিঃ বেল

1
এটি মানদণ্ডের ব্যর্থতা, এবং এটি এখন আরও খারাপ হচ্ছে যে নলের বিপরীতে তুলনা স্থায়ীভাবে SQL সার্ভার ২০১ und হিসাবে এএনএসআই নূলসকে স্থায়ীভাবে সেট করা হিসাবে স্থায়ীভাবে স্থির করা হয়। নাল একটি অজানা মান উপস্থাপন করতে পারে , তবে "নাল" নিজেই একটি অজানা মান নয়। নাল মানটির সাথে নাল মানের তুলনা করা একেবারে সত্য হওয়া উচিত, তবে দুর্ভাগ্যক্রমে বুলিয়ান যুক্তি হিসাবে সাধারণ জ্ঞান থেকে প্রস্থান করা হয়।
ট্রায়ঙ্কো

উত্তর:


126

লিনাক-টু-এসকিউএল-র জন্য কার্যকরী:

var result = from entry in table
             where entry.something.Equals(value)
             select entry;

লিনাক-টু-সত্তা (আউচ!) এর জন্য কার্যপ্রণালী:

var result = from entry in table
             where (value == null ? entry.something == null : entry.something == value)
             select entry;

এটি একটি বাজে বাগ যা আমাকে বেশ কয়েকবার কামড় দিয়েছে। যদি এই বাগটি আপনাকেও প্রভাবিত করে থাকে তবে দয়া করে ইউজারভয়েসের বাগ রিপোর্টটি দেখুন এবং মাইক্রোসফ্টকে জানান যে এই বাগটি আপনাকেও প্রভাবিত করেছে।


সম্পাদনা করুন: এই বাগটি EF 4.5ঠিক করা হচ্ছে ! এই বাগটিকে সমর্থন করার জন্য সবাইকে ধন্যবাদ!

পিছনের সামঞ্জস্যের জন্য, এটি অপ্ট-ইন হবে - আপনাকে entry == valueকাজ করতে ম্যানুয়ালি একটি সেটিংস সক্ষম করতে হবে । এই সেটিংটি কী তা নিয়ে এখনও কোনও শব্দ নেই। সাথে থাকুন!


সম্পাদনা 2: ইএফ দলের এই পোস্ট অনুসারে , এই ইস্যুটি EF6 এ স্থির করা হয়েছে! সাব্বাস!

আমরা ত্রি-মূল্যবান যুক্তির জন্য ক্ষতিপূরণ দিতে EF6 এর ডিফল্ট আচরণটি পরিবর্তন করেছি।

এর অর্থ হ'ল বিদ্যমান কোড যা পুরানো আচরণের উপর নির্ভর করে ( null != nullতবে কেবলমাত্র কোনও ভেরিয়েবলের সাথে তুলনা করার সময়) হয় সেই আচরণের উপর নির্ভর না করার জন্য পরিবর্তন করতে হবে বা UseCSharpNullComparisonBehaviorপুরানো ভাঙা আচরণটি ব্যবহার করতে মিথ্যাতে সেট করা হবে।


6
আমি বাগ রিপোর্টটি ভোট দিয়েছি। আশা করি তারা এটিকে ঠিক করেছেন। আমি বলতে পারব না যে আমি সত্যিই vs2010 বিটা এই বাগ হচ্ছে বর্তমান ... মনে রাখবেন
noobish

2
ওহ মাইক্রোসফ্টে আসুন ... আসলে?!?!? সংস্করণে 4.1?!?! +1
ডেভিড

1
যে লিনাক-টু-এসকিউএল কার্যবিবরণী কাজ করছে বলে মনে হচ্ছে না (কোনও গাইডের সাথে চেষ্টা করছেন?)। সত্তা-ওয়ারাকারআউন্ড ব্যবহার করে L2S এ কাজ করে তবে ভয়াবহ এসকিউএল উত্পন্ন হয়। কোডে আমাকে যদি একটি বিবৃতি করতে হয়(var result = from ...; if(value.HasValue) result = result.Where(e => e.something == value) else result = result.Where(e => e.something == null);
মাইকেল স্টাম

5
অবজেক্ট.একুয়ালস আসলে কাজ করে(where Object.Equals(entry.something,value))
মাইকেল স্টাম

5
@ leen3o (বা অন্য কেউ) - এই অভিযোগযুক্ত ফিক্স ইএফ 4.5 / 5.0 এ রয়েছে এমন কেউ কি এখনও খুঁজে পেয়েছেন? আমি 5.0 ব্যবহার করছি এবং এটি এখনও খারাপ ব্যবহার করছে।
শৌল বেহর

17

সত্তা ফ্রেমওয়ার্ক 5.0 যেহেতু আপনি আপনার সমস্যা সমাধানের জন্য নিম্নলিখিত কোডগুলি ব্যবহার করতে পারেন:

public abstract class YourContext : DbContext
{
  public YourContext()
  {
    (this as IObjectContextAdapter).ObjectContext.ContextOptions.UseCSharpNullComparisonBehavior = true;
  }
}

এটি আপনার সমস্যার সমাধান করবে কারণ সত্তা ফ্রেমওয়ার্কটি 'সি # লাইক' নাল তুলনা ব্যবহার করবে।


16

লিনকিউ থেকে সত্তার সাথে কিছুটা সহজ কাজ রয়েছে:

var result = from entry in table
         where entry.something == value || (value == null && entry.something == null)
         select entry;

এটি এজেডের নজরে পড়ার সাথে সাথে কাজ করে, যেমন লিনকিউ থেকে সত্তা বিশেষ ক্ষেত্রে এক্স == নাল (অর্থাত নাল ধ্রুবকের বিপরীতে সমতার তুলনা) এবং এটি এক্স ন্যূলে অনুবাদ করে।

আমরা বর্তমানে এই আচরণটি পরিবর্তনের জন্য বিবেচনা করছি যদি ক্ষতিপূরণ তুলনা স্বয়ংক্রিয়ভাবে উভয় পক্ষই সামঞ্জস্যপূর্ণ হয় তবে ক্ষতিপূরণ তুলনাগুলি স্বয়ংক্রিয়ভাবে প্রবর্তন করতে পারি। যদিও বেশ কয়েকটি চ্যালেঞ্জ রয়েছে:

  1. এটি ইতিমধ্যে বিদ্যমান আচরণের উপর নির্ভর করে এমন কোডটি ভঙ্গ করতে পারে।
  2. কোনও নাল প্যারামিটার খুব কম ব্যবহৃত হয়ে গেলেও নতুন অনুবাদটি বিদ্যমান ক্যোয়ারগুলির কার্য সম্পাদনকে প্রভাবিত করতে পারে।

যাই হোক না কেন, আমরা এটির জন্য কাজ করব কিনা তা আমাদের গ্রাহকরা এটি নির্ধারিত তুলনামূলক অগ্রাধিকারের উপর নির্ভর করে। আপনি যদি সমস্যাটি সম্পর্কে চিন্তা করেন তবে আমি আপনাকে আমাদের নতুন বৈশিষ্ট্য পরামর্শ সাইট: https://data.uservoice.com এ ভোট দেওয়ার জন্য উত্সাহিত করি ।


9

যদি এটি একটি অযোগ্য প্রকারের হয় তবে সম্ভবত হ্যাসভ্যালু সম্পত্তি ব্যবহার করার চেষ্টা করবেন?

var result = from entry in table
                 where !entry.something.HasValue
                 select entry;

এখানে পরীক্ষা করার জন্য কোনও ইএফ রাখবেন না ... কেবলমাত্র একটি পরামর্শ =)


1
ঠিক আছে ... এটি কেবল তখনই কাজ করে যদি আপনি কেবল নালাগুলি সন্ধান করেন, তবে তারপরে ব্যবহার == nullকরে কোনওভাবেই বাগটি আঘাত হানে না। বিন্দুটি একটি ভেরিয়েবলের মান দ্বারা ফিল্টার করা হয়, যার মান নাল হতে পারে এবং নাল মানটি নাল রেকর্ডগুলি সন্ধান করতে পারে।
ডেভ কাজিনো

1
আপনার উত্তর আমাকে বাঁচিয়েছে। আমি আমার সত্তা মডেল ক্লাসে একটি nlalable টাইপ ব্যবহার করতে ভুলে গিয়েছিলাম এবং (x => x.Column == null)কাজ করতে পারে না । :)
রিবেইরো

এটি দেয় System.NullReferenceException , যেহেতু অলড্রেড অবজেক্টটি বাতিল!
টিআইবিএম


5

Object.Equals()পরিবর্তে নুল তুলনা ব্যবহারের সাথে ডিল করতে==

এই রেফারেন্স পরীক্ষা করুন


এটি লিনক-টু-এসকিএলে পুরোপুরি কাজ করে এবং যথাযথ এসকিউএল উত্পন্ন করে (এখানে কিছু অন্যান্য উত্তর ভয়ঙ্কর এসকিউএল বা ভুল ফলাফল উত্পন্ন করে)।
মাইকেল স্টাম

ধরুন আমি compaire করতে চান null, Object.Equals(null), যদি Objectনিজেই নাল হয়?
তিয়েবএম

4

নির্দেশ করে যে সত্তা ফ্রেমওয়ার্কের সমস্ত <6.0 পরামর্শ কিছু বিশ্রী এসকিউএল জেনারেট করে। "পরিষ্কার" সমাধানের জন্য দ্বিতীয় উদাহরণ দেখুন।

হাস্যকর কাজ

// comparing against this...
Foo item = ...

return DataModel.Foos.FirstOrDefault(o =>
    o.ProductID == item.ProductID
    // ridiculous < EF 4.5 nullable comparison workaround http://stackoverflow.com/a/2541042/1037948
    && item.ProductStyleID.HasValue ? o.ProductStyleID == item.ProductStyleID : o.ProductStyleID == null
    && item.MountingID.HasValue ? o.MountingID == item.MountingID : o.MountingID == null
    && item.FrameID.HasValue ? o.FrameID == item.FrameID : o.FrameID == null
    && o.Width == w
    && o.Height == h
    );

এসকিউএল এর ফলাফলগুলি:

SELECT TOP (1) [Extent1].[ID]                 AS [ID],
       [Extent1].[Name]               AS [Name],
       [Extent1].[DisplayName]        AS [DisplayName],
       [Extent1].[ProductID]          AS [ProductID],
       [Extent1].[ProductStyleID]     AS [ProductStyleID],
       [Extent1].[MountingID]         AS [MountingID],
       [Extent1].[Width]              AS [Width],
       [Extent1].[Height]             AS [Height],
       [Extent1].[FrameID]            AS [FrameID],
FROM   [dbo].[Foos] AS [Extent1]
WHERE  (CASE
  WHEN (([Extent1].[ProductID] = 1 /* @p__linq__0 */)
        AND (NULL /* @p__linq__1 */ IS NOT NULL)) THEN
    CASE
      WHEN ([Extent1].[ProductStyleID] = NULL /* @p__linq__2 */) THEN cast(1 as bit)
      WHEN ([Extent1].[ProductStyleID] <> NULL /* @p__linq__2 */) THEN cast(0 as bit)
    END
  WHEN (([Extent1].[ProductStyleID] IS NULL)
        AND (2 /* @p__linq__3 */ IS NOT NULL)) THEN
    CASE
      WHEN ([Extent1].[MountingID] = 2 /* @p__linq__4 */) THEN cast(1 as bit)
      WHEN ([Extent1].[MountingID] <> 2 /* @p__linq__4 */) THEN cast(0 as bit)
    END
  WHEN (([Extent1].[MountingID] IS NULL)
        AND (NULL /* @p__linq__5 */ IS NOT NULL)) THEN
    CASE
      WHEN ([Extent1].[FrameID] = NULL /* @p__linq__6 */) THEN cast(1 as bit)
      WHEN ([Extent1].[FrameID] <> NULL /* @p__linq__6 */) THEN cast(0 as bit)
    END
  WHEN (([Extent1].[FrameID] IS NULL)
        AND ([Extent1].[Width] = 20 /* @p__linq__7 */)
        AND ([Extent1].[Height] = 16 /* @p__linq__8 */)) THEN cast(1 as bit)
  WHEN (NOT (([Extent1].[FrameID] IS NULL)
             AND ([Extent1].[Width] = 20 /* @p__linq__7 */)
             AND ([Extent1].[Height] = 16 /* @p__linq__8 */))) THEN cast(0 as bit)
END) = 1

ভয়াবহ ওয়ার্কারআউন্ড

আপনি যদি ক্লিনার এসকিউএল উত্পন্ন করতে চান তবে এর মতো কিছু:

// outrageous < EF 4.5 nullable comparison workaround http://stackoverflow.com/a/2541042/1037948
Expression<Func<Foo, bool>> filterProductStyle, filterMounting, filterFrame;
if(item.ProductStyleID.HasValue) filterProductStyle = o => o.ProductStyleID == item.ProductStyleID;
else filterProductStyle = o => o.ProductStyleID == null;

if (item.MountingID.HasValue) filterMounting = o => o.MountingID == item.MountingID;
else filterMounting = o => o.MountingID == null;

if (item.FrameID.HasValue) filterFrame = o => o.FrameID == item.FrameID;
else filterFrame = o => o.FrameID == null;

return DataModel.Foos.Where(o =>
    o.ProductID == item.ProductID
    && o.Width == w
    && o.Height == h
    )
    // continue the outrageous workaround for proper sql
    .Where(filterProductStyle)
    .Where(filterMounting)
    .Where(filterFrame)
    .FirstOrDefault()
    ;

আপনি প্রথম স্থানে যা চেয়েছিলেন তার ফলাফল:

SELECT TOP (1) [Extent1].[ID]                 AS [ID],
           [Extent1].[Name]               AS [Name],
           [Extent1].[DisplayName]        AS [DisplayName],
           [Extent1].[ProductID]          AS [ProductID],
           [Extent1].[ProductStyleID]     AS [ProductStyleID],
           [Extent1].[MountingID]         AS [MountingID],
           [Extent1].[Width]              AS [Width],
           [Extent1].[Height]             AS [Height],
           [Extent1].[FrameID]            AS [FrameID],
FROM   [dbo].[Foos] AS [Extent1]
WHERE  ([Extent1].[ProductID] = 1 /* @p__linq__0 */)
   AND ([Extent1].[Width] = 16 /* @p__linq__1 */)
   AND ([Extent1].[Height] = 20 /* @p__linq__2 */)
   AND ([Extent1].[ProductStyleID] IS NULL)
   AND ([Extent1].[MountingID] = 2 /* @p__linq__3 */)
   AND ([Extent1].[FrameID] IS NULL)

এসকিউএল-তে চলমান কোডটি আরও পরিষ্কার এবং দ্রুত হবে তবে এসএফএল সার্ভারে প্রেরণের পূর্বে EF প্রতিটি সংমিশ্রণের জন্য নতুন কোয়েরি প্ল্যান উত্পন্ন করে এবং ক্যাশে করবে, যা এটি অন্য কাজের ক্ষেত্রের চেয়ে ধীর করে তোলে।
বুড়ক তমতর্ক

2
var result = from entry in table
                     where entry.something == null
                     select entry;

উপরের প্রশ্নগুলি ইচ্ছাকৃতভাবে কাজ করে। এটি সঠিকভাবে ইস নাল জেনারেট করে। আমার প্রোডাকশন কোডটি কিন্তু ছিল

var value = null;
var result = from entry in table
                         where entry.something == value
                         select entry;

এবং উত্পন্ন এসকিউএল কিছু ছিল = @ পি; @ পি = নাল দেখে মনে হয় যে EF সঠিকভাবে ধ্রুবক ভাবটি অনুবাদ করে তবে কোনও ভেরিয়েবল জড়িত থাকলে এটি এটি একটি সাধারণ তুলনার মতোই আচরণ করে। আসলে জ্ঞান করে।


1

দেখা যাচ্ছে যে লিনক 2 এসকিএল-তেও এই "সমস্যা" রয়েছে। মনে হয় যে এএনএসআই নালস চালু আছে বা বন্ধ রয়েছে তার কারণে এই আচরণের একটি বৈধ কারণ রয়েছে তবে এটি আপনার মনকে যেমন উদ্ঘাটিত করে তোলে যে কেন সরাসরি "== নাল" আপনার প্রত্যাশা মতো কাজ করবে।


1

ব্যক্তিগতভাবে, আমি পছন্দ করি:

var result = from entry in table    
             where (entry.something??0)==(value??0)                    
              select entry;

উপর

var result = from entry in table
             where (value == null ? entry.something == null : entry.something == value)
             select entry;

কারণ এটি পুনরাবৃত্তি প্রতিরোধ করে - যদিও এটি গাণিতিকভাবে সঠিক নয়, তবে এটি বেশিরভাগ ক্ষেত্রেই ফিট করে।


0

আমি দিভেগার পোস্টটি মন্তব্য করতে সক্ষম নই, তবে এখানে উপস্থাপন করা বিভিন্ন সমাধানগুলির মধ্যে, দিভেগার সমাধানটি সেরা এসকিউএল উত্পাদন করে। উভয় পারফরম্যান্স বুদ্ধিমান এবং দৈর্ঘ্য বুদ্ধিমান। আমি সবেমাত্র এসকিউএল সার্ভার প্রোফাইলারের সাথে এবং এক্সিকিউশন প্ল্যানটি দেখে ("সেট স্ট্যাটিক্সস প্রোফাইলে চালু") দিয়েছি।


0

দুর্ভাগ্যক্রমে সত্তা ফ্রেমওয়ার্ক 5 ডিবি কনটেক্সটে সমস্যাটি এখনও ঠিক হয়নি।

আমি এই কার্যটি ব্যবহার করেছি (এমএসএসকিউএল ২০১২ এর সাথে কাজ করে তবে এএনএসআই নুলস সেটিংটি ভবিষ্যতের কোনও এমএসএসকিউএল সংস্করণে অবচয় করা হতে পারে)।

public class Context : DbContext
{

    public Context()
        : base("name=Context")
    {
        this.Database.Connection.StateChange += Connection_StateChange;
    }

    void Connection_StateChange(object sender, System.Data.StateChangeEventArgs e)
    {
        // Set ANSI_NULLS OFF when any connection is opened. This is needed because of a bug in Entity Framework
        // that is not fixed in EF 5 when using DbContext.
        if (e.CurrentState == System.Data.ConnectionState.Open)
        {
            var connection = (System.Data.Common.DbConnection)sender;
            using (var cmd = connection.CreateCommand())
            {
                cmd.CommandText = "SET ANSI_NULLS OFF";
                cmd.ExecuteNonQuery();
            }
        }
    }
}

এটি লক্ষ্য করা উচিত যে এটি একটি নোংরা কাজ কিন্তু এটি খুব দ্রুত প্রয়োগ করা যেতে পারে এবং সমস্ত প্রশ্নের জন্য কাজ করে।


সতর্কতাটি পরিষ্কার না হলে সেক্ষেত্রে এসএনএল সার্ভারের ভবিষ্যতের সংস্করণে এএনএসআই নুলস স্থায়ীভাবে চালু হয়ে গেলে এটি তত্ক্ষণাত্ বন্ধ হয়ে যাবে।
ট্রায়ঙ্কো

0

আপনি যদি আমার মতো পদ্ধতি (ল্যাম্বদা) সিনট্যাক্স ব্যবহার করতে পছন্দ করেন তবে আপনি একই জিনিসটি করতে পারেন:

var result = new TableName();

using(var db = new EFObjectContext)
{
    var query = db.TableName;

    query = value1 == null 
        ? query.Where(tbl => tbl.entry1 == null) 
        : query.Where(tbl => tbl.entry1 == value1);

    query = value2 == null 
        ? query.Where(tbl => tbl.entry2 == null) 
        : query.Where(tbl => tbl.entry2 == value2);

    result = query
        .Select(tbl => tbl)
        .FirstOrDefault();

   // Inspect the value of the trace variable below to see the sql generated by EF
   var trace = ((ObjectQuery<REF_EQUIPMENT>) query).ToTraceString();

}

return result;

-1
var result = from entry in table    
             where entry.something == value||entry.something == null                   
              select entry;

যে ব্যবহার


5
এটি খুব ভুল কারণ এটি মানটি মেলে এমন সমস্ত এন্ট্রি নির্বাচন করবে এবং যেখানে কোনও মান শূন্য রয়েছে এমন সমস্ত প্রবেশিকা নির্বাচন করবে you
মাইকেল স্টাম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.