EF में DateTime से केवल दिनांक घटकों की तुलना कैसे करें?


116

मेरे पास दो दिनांक मान हैं, एक पहले से ही डेटाबेस में संग्रहीत है और दूसरा DatePicker का उपयोग करके उपयोगकर्ता द्वारा चुना गया है। उपयोग का मामला डेटाबेस से किसी विशेष तिथि की खोज करना है।

डेटाबेस में पहले दर्ज किया गया मान हमेशा 12:00:00 का समय घटक होता है, जहां पिकर से दर्ज की गई तारीख में अलग-अलग समय घटक होता है।

मुझे केवल दिनांक घटकों में दिलचस्पी है और मैं समय घटक की उपेक्षा करना चाहूंगा।

C # में इस तुलना को करने के तरीके क्या हैं?

इसके अलावा, यह LINQ में कैसे करें?

अद्यतन: LINQ पर संस्थाओं के लिए, निम्नलिखित ठीक काम करता है।

e => DateTime.Compare(e.FirstDate.Value, SecondDate) >= 0

1
आप इस SO प्रश्न पर भी नज़र डाल सकते हैं: stackoverflow.com/questions/683037/how-to-compare-dates-in-c/…
क्विंटिन रॉबिन्सन

जवाबों:


121

नोट: इस उत्तर को लिखने के समय, EF- संबंध अस्पष्ट था (जो इस प्रश्न के लिखे जाने के बाद संपादित किया गया था)। ईएफ के साथ सही दृष्टिकोण के लिए, मंदीप जवाब की जांच करें ।


आप DateTime.Dateकेवल-दिनांक की तुलना करने के लिए संपत्ति का उपयोग कर सकते हैं ।

DateTime a = GetFirstDate();
DateTime b = GetSecondDate();

if (a.Date.Equals(b.Date))
{
    // the dates are equal
}

34
दिनांक की तुलना करना आसान है, लेकिन प्रश्न LINQ से संबंधित संस्थाओं के लिए है जो कन्वर्ट करने में असमर्थ है। संपत्ति को SQL में बदलें।
माइकल कार्ल 14

1
@ MichaëlCarpentier: अच्छी बात है। जाहिर तौर पर इसने अभी भी ओपी की समस्या को हल कर दिया है।
फ्रेड्रिक मोर

6
यह डेटाबेस को क्वेरी नहीं करता है, बल्कि तथ्य के बाद CLR / एप्लिकेशन लेयर में डेटा को प्रोसेस करता है। वास्तविक समाधान EntityFunctions.TruncateTime (..) फ़ंक्शन का उपयोग नीचे दिए गए जवाब में निर्दिष्ट है, क्योंकि यह डेटाबेस को क्वेरी भेजता है और भंडारण परत पर प्रसंस्करण करने की अनुमति देता है। इसके बिना आप दिनांक की तुलना लॉजिक का उपयोग कहां / काउंट क्लॉस में नहीं कर सकते हैं और फिर फ़िल्टर किए गए डेटा पर आगे क्वेरी कर सकते हैं, क्योंकि आपको आंशिक परिणाम पहले आवेदन परत में खींचना होगा, जो परिदृश्यों में एक सौदा-ब्रेकर हो सकता है जो डेटा के बड़े निकायों की प्रक्रिया करें।
मार्च्य

6
@ मार्की हाँ, EntityFunctions.TruncateTimeनिश्चित रूप से इन दिनों जाने का रास्ता प्रतीत होता है (यह .NET 4 में उपलब्ध हो गया था जो इस प्रश्न के पूछे जाने के एक साल बाद जारी किया गया था)।
फ्रेड्रिक मोर्क

1
System.Data.Entity.DbFunctions.TruncateTime () विधि का उपयोग करें। आपको EntityFramework
adeel41

132

EntityFunctionsसमय भाग को ट्रिम करने के लिए कक्षा का उपयोग करें ।

using System.Data.Objects;    

var bla = (from log in context.Contacts
           where EntityFunctions.TruncateTime(log.ModifiedDate) ==  EntityFunctions.TruncateTime(today.Date)
           select log).FirstOrDefault();

स्रोत: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/84d4e18b-7545-419b-9826-53ff1a0e2a62/

अपडेट करें

EF 6.0 और बाद में EntityFunctions को DbFunctions द्वारा बदल दिया जाता है ।


37
बस (कम से कम) EF6 के EntityFunctionsपक्ष में एक नोट System.Data.Entity.DbFunctionsनिकाला गया है। हो सकता है कि यह इससे पहले हो।
पक्वेस्ट

4
मुझे इस समाधान पर कूदने की जल्दी नहीं होगी क्योंकि यह वास्तव में धीमा है, अधिक जानकारी: stackoverflow.com/questions/22776843/…
पाजिक्स

SQLite डेटाबेस के साथ काम करने के लिए प्रतीत नहीं होता है। मुझे "SQL लॉजिक एरर या मिसिंग डेटाबेस नो फंक्शन: ट्रंकैटटाइम" मिलता है।
शैडोरा

24

मुझे लगता है कि यह आपकी मदद कर सकता है।

मैंने एक विस्तार किया क्योंकि मुझे EF डेटा से भरे हुए रिपॉजिटरी में तारीखों की तुलना करनी है। इसलिए यह एक विकल्प नहीं था क्योंकि यह LinqToEntities अनुवाद में लागू नहीं है।

यहाँ कोड है:

        /// <summary>
    /// Check if two dates are same
    /// </summary>
    /// <typeparam name="TElement">Type</typeparam>
    /// <param name="valueSelector">date field</param>
    /// <param name="value">date compared</param>
    /// <returns>bool</returns>
    public Expression<Func<TElement, bool>> IsSameDate<TElement>(Expression<Func<TElement, DateTime>> valueSelector, DateTime value)
    {
        ParameterExpression p = valueSelector.Parameters.Single();

        var antes = Expression.GreaterThanOrEqual(valueSelector.Body, Expression.Constant(value.Date, typeof(DateTime)));

        var despues = Expression.LessThan(valueSelector.Body, Expression.Constant(value.AddDays(1).Date, typeof(DateTime)));

        Expression body = Expression.And(antes, despues);

        return Expression.Lambda<Func<TElement, bool>>(body, p);
    }

तो आप इसे इस तरह से उपयोग कर सकते हैं।

 var today = DateTime.Now;
 var todayPosts = from t in turnos.Where(IsSameDate<Turno>(t => t.MyDate, today))
                                      select t);

10

यदि आप DateDB संस्थाओं के लिए संपत्ति का उपयोग करते हैं तो आपको अपवाद मिलेगा:

"The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."

आप कुछ इस तरह का उपयोग कर सकते हैं:

  DateTime date = DateTime.Now.Date;

  var result = from client in context.clients
               where client.BirthDate >= date
                     && client.BirthDate < date.AddDays(1)
               select client;

8

LINQ में Entities को करने के लिए, आपको समर्थित विधियों का उपयोग करना होगा :

var year = someDate.Year;
var month = ...
var q = from r in Context.Records
        where Microsoft.VisualBasic.DateAndTime.Year(r.SomeDate) == year 
              && // month and day

बदसूरत, लेकिन यह काम करता है, और यह DB सर्वर पर किया जाता है।


8

इसे करने का एक अलग तरीका है, लेकिन यह केवल तभी उपयोगी है जब SecondDate एक चर है जिसमें आप गुजर रहे हैं:

DateTime startDate = SecondDate.Date;
DateTime endDate = startDate.AddDays(1).AddTicks(-1);
...
e => e.FirstDate.Value >= startDate && e.FirstDate.Value <= endDate

मुझे लगता है कि काम करना चाहिए


1
अति उत्कृष्ट। मेरे लिए काम किया। यह स्पष्ट था कि DateTime = x.Date;मैं गायब था। यदि मैंने उपयोग किया था var, या इसकी तुलना में मूल्य इनलाइन था, जो रिपोर्ट किए गए अपवाद के साथ विफल रहा। धन्यवाद।
टिम क्रॉयडन

खुशी है कि यह काम किया, टिम। जवाब में देरी के लिए खेद है - मैं वास्तव में थोड़ी देर में एसओ में प्रवेश नहीं किया है।
जॉन केस्टर

1
यदि आप को बदलने के e.FirstDate.Value <= endDateलिए e.FirstDate.Value < endDateआप को हटा सकते हैं .AddTicks(-1)
मार्को डे ज़ीव्यू

@MarcodeZeeuw तुम सही हो, यह निश्चित रूप से भी काम करेगा। दिखाई गई सशर्त अभिव्यक्ति सटीक प्रारंभ और अंत डेटासेट की समावेशी तिथि तुलना के लिए अभिप्रेत है (यह मानते हुए कि दिनांक सीमा मान कोड विखंडन में सेट होने के बजाय स्थिति में पारित हो जाएंगे।) IOW, सशर्त को डेटाइम मानों से अलग माना जाता है। ।
जॉन केस्टर

6

आप इसका उपयोग भी कर सकते हैं:

DbFunctions.DiffDays(date1, date2) == 0


4

आप इसके लिए DbFunctions.TruncateTime () विधि का उपयोग कर सकते हैं।

e => DbFunctions.TruncateTime(e.FirstDate.Value) == DbFunctions.TruncateTime(SecondDate);

3

हमेशा पूर्ण तिथि समय के बजाय, हमेशा दिनांक समय की दिनांक संपत्ति की तुलना करें ।

जब आप अपनी LINQ क्वेरी बनाते हैं, तो डेट का उपयोग करें। क्वेरी में, यानी:

var results = from c in collection
              where c.Date == myDateTime.Date
              select c;

10
मुझे त्रुटि मिल रही है "निर्दिष्ट प्रकार के सदस्य 'तिथि' LINQ में संस्थाओं को समर्थित नहीं है। केवल शुरुआती, इकाई सदस्यों और इकाई नेविगेशन गुणों का समर्थन किया जाता है।" कोई विचार?
पेन्सिलस्लेट

हाँ - आपका प्रदाता सीधे .Date संपत्ति को संभालता नहीं है। आपको इसे बाहर निकालना होगा, और बाद में तारीखों की तुलना करनी होगी।
रीड कोपसे

दुर्भाग्यवश Linq To Entities में इस्तेमाल नहीं किया जा सकता है। उम्मीद है कि एमएस जल्द ही उस अधिभार समर्थन को जोड़ देगा
जॉन केस्टर

1
हमेशा दिनांक संपत्ति की तुलना करें? मैंने इस टिप्पणी पर ध्यान नहीं दिया है क्योंकि मैंने सोचा है कि क्या यह सबसे अच्छा अभ्यास है, अर्थात। करने के लिए हमेशा की तारीख संपत्ति, तब भी जब यह की तरह कुछ का उपयोग candidate.Date >= base.Date। सैद्धांतिक रूप से, candidate.Dateसमय होना चाहिए = = 12:00:00, इसलिए दिनांक संपत्ति का उपयोग करना निरर्थक है, लेकिन मैं रीड की सलाह के साथ रहूंगा।
स्टीफन होकिंग


2

// लाइनक यूजर्स / कोडर्स के लिए ध्यान दें

यह जाँचने के लिए आपको सटीक तुलना देनी चाहिए कि क्या किसी उपयोगकर्ता द्वारा इनपुट के साथ काम करने के दौरान कोई तिथि सीमा में आती है - उदाहरण के लिए दिनांक पिकर:

((DateTime)ri.RequestX.DateSatisfied).Date >= startdate.Date &&
        ((DateTime)ri.RequestX.DateSatisfied).Date <= enddate.Date

जहां प्रारंभ और समाप्ति तिथि पिकर से मान हैं।


1

इस तरह की कोशिश के बिना समय के बिना:

TimeSpan ts = new TimeSpan(23, 59, 59);
toDate = toDate.Add(ts);
List<AuditLog> resultLogs = 
    _dbContext.AuditLogs
    .Where(al => al.Log_Date >= fromDate && al.Log_Date <= toDate)
    .ToList();
return resultLogs;

1

आप बिना समय के 2 तारीखों की तुलना करने के लिए नीचे दिए गए लिंक पर उपयोगकर्ता कर सकते हैं:

private bool DateGreaterOrEqual(DateTime dt1, DateTime dt2)
        {
            return DateTime.Compare(dt1.Date, dt2.Date) >= 0;
        }

private bool DateLessOrEqual(DateTime dt1, DateTime dt2)
        {
            return DateTime.Compare(dt1.Date, dt2.Date) <= 0;
        }

फ़ंक्शन की तुलना करें 3 अलग-अलग मान: -1 0 1 जिसका अर्थ है dt1> dt2, dt1 = dt2, df1


आप सिर्फ DateTime.Compare (dt1.Date, dt2.Date) क्यों नहीं लौटाते? यह आप सभी की जरूरत है
जॉनी ग्रेबर

0

इसे आज़माएं ... दो डेटाइम प्रकारों के बीच दिनांक गुणों की तुलना करने के लिए यह ठीक काम करता है:

पुनश्च। यह एक स्टॉपगैप सॉल्यूशन है और वास्तव में बुरा अभ्यास है, इसका इस्तेमाल कभी नहीं करना चाहिए जब आप जानते हैं कि डेटाबेस हजारों रिकॉर्ड ला सकता है ...

query = query.ToList()
             .Where(x => x.FirstDate.Date == SecondDate.Date)
             .AsQueryable();

1
पुनश्च: मैं आमतौर पर इस तरह का उपयोग करता हूं जब DateTimes का समय मूल्य होता है और मैं केवल दिनांक की तुलना करना चाहता हूं।
रस्कुन्हो

2
यह एक बहुत बुरा समाधान है, क्वेरी को सभी रिकॉर्ड मिलेंगे, और उसके बाद ही तिथियों को फ़िल्टर करें। यदि डेटाबेस में लाखों रिकॉर्ड हैं, तो यह उन सभी को हड़प लेगा और उसके बाद ही तिथियों को फ़िल्टर करेगा। बहुत बुरा व्यवहार।
विमुद्रीकरण

1
यह एक स्टॉपगैप सॉल्यूशन और वास्तव में बुरा अभ्यास है, इसका उपयोग कभी नहीं किया जाना चाहिए जब आप जानते हैं कि डेटाबेस हजारों रिकॉर्ड ला सकता है।
रस्कुन्हो

यदि आप अपने जवाब में अपनी टिप्पणी जोड़ते हैं, तो मैं अपना डाउन-वोट हटा दूंगा। इस पृष्ठ पर जाने वाले किसी को भी यह स्पष्ट होना चाहिए कि आपके द्वारा प्रस्तावित समाधान टिप्पणियों को पढ़ने के बिना खराब है।
देहाती

जबकि सामान्य रूप से एक बुरा विचार, इस दृष्टिकोण के परिणामस्वरूप छोटे रिकॉर्ड सेट (<1000 रिकॉर्ड या तो) के लिए बेहद बेहतर प्रदर्शन होता है, क्योंकि ईएफ़टी एसक्यूएल के लिए तारीख की तुलना का अनुवाद करता है। मैंने देखा है कि जो कुछ भी SQL EF जेनरेट करता है, उसकी तुलना में मेमोरी में तारीख की तुलना करने से प्रश्नों को एक मिनट से भी कम समय के भीतर खत्म कर दिया जाता है।
एक्सट्रागोरि
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.