web-dev-qa-db-fra.com

Comment comparer uniquement les composants de date de DateTime dans EF?

J'ai deux valeurs de date, une déjà stockée dans la base de données et l'autre sélectionnée par l'utilisateur à l'aide de DatePicker. Le cas d'utilisation consiste à rechercher une date particulière dans la base de données.

La valeur précédemment entrée dans la base de données a toujours une composante heure de 12:00:00, la date entrée dans le sélecteur ayant une composante heure différente.

Je ne m'intéresse qu'aux composants de la date et je voudrais ignorer le composant de l'heure.

Quels sont les moyens de faire cette comparaison en C #?

Aussi, comment faire cela dans LINQ?

UPDATE: Sur LINQ to Entities, les éléments suivants fonctionnent correctement.

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

REMARQUE: au moment de la rédaction de cette réponse, la relation EF n'était pas claire (elle a été intégrée à la question après sa rédaction). Pour une approche correcte avec EF, vérifiez réponse Mandeeps .


Vous pouvez utiliser le DateTime.Date propriété pour effectuer une comparaison par date.

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

if (a.Date.Equals(b.Date))
{
    // the dates are equal
}
120
Fredrik Mörk

Utilisez la classe EntityFunctions pour rogner la partie temporelle.

using System.Data.Objects;    

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

Source: http://social.msdn.Microsoft.com/Forums/en-US/csharpgeneral/thread/84d4e18b-7545-419b-9826-53ff1a0e2a62/

[~ # ~] met à jour [~ # ~]

A partir de EF 6.0, les EntityFunctions sont remplacées par DbFunctions .

131
Mandeep Janjua

Je pense que cela pourrait vous aider.

J'ai fait une extension car je dois comparer les dates dans des référentiels remplis de données EF. Ainsi, Date n'était pas une option, car il n'est pas implémenté dans la traduction LinqToEntities.

Voici le code:

        /// <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);
    }

alors vous pouvez l'utiliser de cette façon.

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

Si vous utilisez la propriété Date pour les entités de base de données, vous obtiendrez une exception:

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

Vous pouvez utiliser quelque chose comme ceci:

  DateTime date = DateTime.Now.Date;

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

Voici une manière différente de le faire, mais elle n’est utile que si SecondDate est une variable que vous transmettez:

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

Je pense que ça devrait marcher

8
John Kaster

Pour le faire dans LINQ to Entities, vous devez utiliser méthodes supportées :

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

Moche, mais ça marche, et c'est fait sur le serveur de base de données.

8
Craig Stuntz

Vous pouvez également utiliser ceci:

DbFunctions.DiffDays(date1, date2) == 0

6
user3829854

vous pouvez utiliser la méthode DbFunctions.TruncateTime () pour cela.

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

Il suffit de toujours comparer la propriété Date de DateTime au lieu de la date complète.

Lorsque vous effectuez votre requête LINQ, utilisez date.Date dans la requête, c'est-à-dire:

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

C'est comme ça que je fais ça.

DateTime date_time_to_compare = DateTime.Now;
//Compare only date parts
context.YourObject.FirstOrDefault(r =>
                EntityFunctions.TruncateTime(r.date) == EntityFunctions.TruncateTime(date_to_compare));
3
Alejandro del Río

// Note pour les utilisateurs/codeurs Linq

Cela devrait vous donner la comparaison exacte pour vérifier si une date se situe dans la plage lorsque vous utilisez une entrée à partir d'un sélecteur de date utilisateur, par exemple:

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

où startdate et enddate sont les valeurs d'un sélecteur de date.

2
Leo Di Salty

Juste si quelqu'un arrive ici en train de googler ou de bavarder ... Solutions de contournement compilées:

http://blog.integratedsolution.eu/post/2011/02/06/The-specified-type-member-Date-is-not-supported-in-LINQ-to-Entities.aspx

1
Braulio

Sans temps que d'essayer comme ça:

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
Nalan Madheswaran

Vous pouvez utiliser le lien ci-dessous pour comparer 2 dates sans heure:

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;
        }

la fonction Compare renvoie 3 valeurs différentes: -1 0 1, ce qui signifie dt1> dt2, dt1 = dt2, dt1

1
majid

Essayez ceci ... Cela fonctionne bien pour comparer les propriétés de date entre deux types de DateTimes:

PS C'est une solution provisoire et une très mauvaise pratique à ne pas utiliser si vous savez que la base de données peut contenir des milliers d'enregistrements ...

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