0
votes

Comment vérifier existant dans DB pour n'importe quel Room, BookDate et RoomId correspondant?

Comment vérifier s'il existe une entrée dans la base de données? Le débogage montre que le result renvoie null .

TimeSlots une collection. Je ne sais pas si je l'ai fait correctement.

Voici mon contexte:

{
    "RoomId": 1,
    "BookDate": "2020-10-27",
    "TimeSlots": [1, 3],
    "Modules": [1]
}
public class BookingTimeSlot
{
    public int BookingId { get; set; }    
    public int TimeSlotId { get; set; }
    public Booking Booking { get; set; }
    public TimeSlot TimeSlot { get; set; }
}
public class Booking
{
    public int Id { get; set; }

    [Required]
    public DateTime BookDate { get; set; }

    [Required]
    public int RoomId { get; set; }

    public Room Room { get; set; }

    [Required]
    public ICollection<BookingTimeSlot> TimeSlots { get; set; }

    [Required]
    public ICollection<BookingModule> Modules { get; set; }

    public Booking()
    {
        TimeSlots = new Collection<BookingTimeSlot>();
        Modules = new Collection<BookingModule>();
    }
}

Voici l'entrée que j'essaye de faire:

var result = await context.Bookings
    .SingleOrDefaultAsync(b => 
        b.BookDate == booking.BookDate 
        && b.TimeSlots == booking.TimeSlots 
        && b.RoomId == booking.RoomId);


0 commentaires

3 Réponses :


1
votes

Votre question n'est pas claire si vous cherchez à trouver des doublons ou à obtenir le premier résultat.

Deuxièmement, je pense qu'il vous manque la clé primaire dans votre modèle ou que vous utilisez une clé composite, de toute façon, c'est une bonne lecture pour vous aider à résoudre ce problème.

var result = await context.Bookings
    .FirstOrDefaultAsync(b =>        //first result
        b.BookDate == booking.BookDate 
        && b.TimeSlots == booking.TimeSlots 
        && b.RoomId == booking.RoomId);

Si vous voulez juste le premier résultat, changez le chant en premier

//With Linq and EF find and process duplicates     
// assuming Id is your primary key - [please fix this, some info for you][1] 
var duplicateBookings = context.Bookings.GroupBy(i => i.id)
                     .Where(x => x.Count() > 1)
                     .Select(val => val.Key); // or .SelectMany(i => i.ToList());
// do what you need
foreach(var dupes in duplicateBookings )
{
    //process or do what you need
    context.Bookings.DeleteObject(dupes); // for e.g. delete duplicate bookings
}


3 commentaires

Désolé pour l'erreur. Je ne voulais pas vérifier les doublons, mais plutôt si mon entrée correspond à l'un des enregistrements de la base de données.


J'ai essayé FirstOrDefaultAsync mais pas de chance. Il renvoie toujours null .


Ensuite, cela signifie qu'il n'y a pas de correspondance, réduisez-le simplement à var result = await context.Bookings .FirstOrDefaultAsync(b => b.RoomId == booking.RoomId ) et testez-le si vous obtenez des résultats, puis ajoutez plus de conditions. Si cela fonctionne, veuillez marquer comme réponse



1
votes

Eh bien, pour la plupart, l'intégrité référentielle dans la base de données ne résout pas ces problèmes, et dans la grande majorité des cas, RI n'est de toute façon pas utilisé. La raison en est que ce n'est pas le travail de RI, mais pire, ces violations du RI ont tendance à se produire BEAUCOUP TROP tard pour une interface utilisateur qui informe l'utilisateur qu'une telle réservation ne peut pas être effectuée. En d'autres termes, vous n'essayez pas de faire la réservation, gardez les doigts croisés et espérez que les données pourront être écrites.

Ce que vous faites est de fournir une interface utilisateur qui, lorsque l'utilisateur sélectionne une date de réservation, vous donnez des commentaires indiquant qu'une telle réservation ne peut pas être effectuée, et en tant que telle, AUCUNE ÉCRITURE DE BASE DE DONNÉES ni aucune mise à jour n'auront encore eu lieu - il s'agit donc d'un problème d'interface utilisateur, pas vraiment un problème de base de données RI. Et même s'il s'agissait d'un problème de base de données RI, vous auriez à essayer d'écrire les données, et souvent l'utilisateur vérifie et demande juste une date de réservation particulière - pas nécessairement prêt à réserver.

une collision de réservation peut être trouvée sur la base de cette logique:

@dtRequestStartDate = "Enter start Date" 
@dtRequestEndDate = "Enter end date"
@RoomNum = Room number

strSQL = SELECT * from tblBookings where  
         (@dtRequestStartDate <= RoomEndDate)
         AND
         (@dtRequestEndDate >= RoomStartDate)
         AND
         (@RoomNum = RoomNumber)

 If above row.Count > 0 then 
     message = Sorry, you cannot book that room

Ainsi, tout chevauchement ou même un bracketing complet sera trouvé avec la requête simple ci-dessus.

Alors, avec ci-dessus? Ensuite, avec un numéro de chambre et une liste des plages de dates de réservation pour cette chambre, une collision serait trouvée avec ceci:

RequestStartDate <= EndDate 
and 
RequestEndDate >= StartDate 

Donc, ce que vous faites est de vérifier avant une réservation, et si ci-dessus renvoie des lignes, vous n'autorisez pas la réservation. Tant que vous n'autorisez jamais les chevauchements pour les réservations, la logique SIMPLE ci-dessus fonctionnera toujours et empêchera toujours une réservation avec des collisions.


0 commentaires

0
votes

J'ai trouvé une solution à mon problème. Je compare TimeSlotId en utilisant Intersect , s'il y a une intersection, il retourne alors true.

public bool BookingExist(Booking booking)
{
    var resultContext = context.Bookings
        .Where(b => b.Room.Id == booking.RoomId && b.BookDate == booking.BookDate)
        .SelectMany(b => b.TimeSlots.Select(bt => bt.TimeSlotId))
        .AsEnumerable();

    var resultInput = booking.TimeSlots.Select(bt => bt.TimeSlotId);

    if (resultContext.Intersect(resultInput).Count() > 0)
        return true;
    else
        return false;
}


0 commentaires