web-dev-qa-db-fra.com

LINQ Joining in C # with multiple conditions

J'ai une instruction LINQ Joining en C # avec plusieurs conditions.

var possibleSegments = 
    from epl in eventPotentialLegs
    join sd in segmentDurations on 
        new { 
            epl.ITARequestID, 
            epl.ITASliceNumber, 
            epl.DepartAirportAfter, 
            epl.AirportId_Origin, 
            epl.AirportId_Destination 
        } 
        equals 
        new { 
            sd.ITARequestId, 
            sd.SliceIndex, 
            sd.OriginAirport, 
            sd.DestinationAirport 
        }
    where
        epl.DepartAirportAfter > sd.UTCDepartureTime 
        and 
        epl.ArriveAirportBy > sd.UTCArrivalTime
    select new PossibleSegments{ ArrivalTime = sd.arrivalTime };

La jointure ne fonctionne pas correctement. Qu'est-ce que je fais mal?

53
Ratheesh

AFAIK, vous ne pouvez rejoindre que de cette façon:

var query = from obj_i in set1
join obj_j in set2 on 
    new { 
      JoinProperty1 = obj_i.SomeField1,
      JoinProperty2 = obj_i.SomeField2,
      JoinProperty3 = obj_i.SomeField3,
      JoinProperty4 = obj_i.SomeField4
    } 
    equals 
    new { 
      JoinProperty1 = obj_j.SomeOtherField1,
      JoinProperty2 = obj_j.SomeOtherField2,
      JoinProperty3 = obj_j.SomeOtherField3,
      JoinProperty4 = obj_j.SomeOtherField4
    }

Les exigences principales sont: les noms de propriété, les types et l'ordre dans les objets anonymes sur lesquels vous vous joignez doivent correspondre.

Vous NE POUVEZ PAS utiliser ET ET OU etc. dans les jointures. Juste object1 est égal à object2.

Des choses plus avancées dans cet exemple LinqPad:

class c1 
    {
    public int someIntField;
    public string someStringField;
    }

class c2 
    {
    public Int64 someInt64Property {get;set;}
    private object someField;
    public string someStringFunction(){return someField.ToString();}
    }

void Main()
{
    var set1 = new List<c1>();
    var set2 = new List<c2>();

    var query = from obj_i in set1
    join obj_j in set2 on 
        new { 
                JoinProperty1 = (Int64) obj_i.someIntField,
                JoinProperty2 = obj_i.someStringField
            } 
        equals 
        new { 
                JoinProperty1 = obj_j.someInt64Property,
                JoinProperty2 = obj_j.someStringFunction()
            }
    select new {obj1 = obj_i, obj2 = obj_j};
}

L'adressage des noms et de l'ordre des propriétés est simple, les types d'adressage peuvent être obtenus via des méthodes de conversion/conversion/analyse/appel, etc. au moment de l'exécution, donc YMMV. Cela est dû au fait qu'ils sont copiés dans des propriétés publiques en lecture seule dans les objets anonymes, donc tant que votre expression produit des valeurs de type correct, la propriété join - tout devrait bien se passer.

96
Zar Shardan

Votre and doit être un && dans la clause where.

where epl.DepartAirportAfter >  sd.UTCDepartureTime 
and epl.ArriveAirportBy > sd.UTCArrivalTime

devrait être

where epl.DepartAirportAfter >  sd.UTCDepartureTime 
&& epl.ArriveAirportBy > sd.UTCArrivalTime
5
p.campbell

Si vous n'avez pas besoin de conditions d'objet égales, utilisez des séquences de jointure croisée:

var query = from obj1 in set1
from obj2 in set2
where obj1.key1 == obj2.key2 && obj1.key3.contains(obj2.key5) [...conditions...]
0
Qio