1
votes

Quelles sont les différences entre & et && dans EF Core

Je comprends que && court-circuite l'évaluation afin qu'elle n'ait pas à évaluer le RHS si ce n'est pas nécessaire, mais qu'en est-il de l'EF? Y a-t-il des différences entre & et && (idem pour | et ||)? en termes de performances!


1 commentaires

Si vous en avez besoin pour ef (Core ou non) et que vous voulez des conditions, je vous suggère de toujours utiliser && ou ||. Parce que les opérateurs au niveau du bit sont hors de votre expérience pour le moment.


3 Réponses :


2
votes

Selon la documentation Microsoft:

1.Le & Operator est pris en charge sous deux formes: un opérateur d'adresse unaire ou un opérateur logique binaire.

Opérateur d'adresse unaire:

L'opérateur unaire & renvoie l'adresse de son opérande. Pour plus d'informations, consultez Comment: obtenir l'adresse d'une variable . L'opérateur d'adresse de & requiert un contexte non sécurisé.

Opérateur AND logique au niveau du bit entier:

Pour les types entiers, le & calcule le bit logique AND de ses opérandes:

bool SecondOperand()
{
    Console.WriteLine("Second operand is evaluated.");
    return true;
}

bool a = false && SecondOperand(); // <-- second operand is not evaluated here
Console.WriteLine(a);
// Output:
// False

bool b = true && SecondOperand(); // <-- second operand is evaluated here
Console.WriteLine(b);
// Output:
// Second operand is evaluated.
// True

2. Le && Operator est l'opérateur AND logique conditionnel, également appelé l'opérateur ET logique "court-circuitant", calcule le ET logique de ses opérandes booléens. Le résultat de x && y est vrai si les deux x et y évaluent à true . Sinon, le résultat est false . Si le premier opérande est évalué à false , le deuxième opérande n'est pas évalué et le résultat de l'opération est false . L'exemple suivant illustre ce comportement:

uint a = 0b_1111_1000;
uint b = 0b_1001_1111;
uint c = a & b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10011000

Maintenant, dans le cas du comportement EF / EF Core, @Ivan Stoev l'a beaucoup expliqué: Ici


1 commentaires

Merci @TanvirArjel, la question concerne le comportement EF



6
votes

mais qu'en est-il d'EF? Y a-t-il des différences entre & et && (idem pour | et ||)? en termes de performances!

Oui, c'est le cas.

Premièrement, EF Core utilise parfois évaluation du client , donc il ne peut pas être court-circuité.

Deuxièmement, même lors de l'utilisation de l'évaluation du serveur, EF Core les traduit différemment. Par exemple, voici la traduction pour SqlServer:

LINQ             SQL
==============   ============ 
expr1 && expr2   expr1 AND expr2
expr1 & expr2    (expr1 & expr2) = 1

La question de savoir si cela affecte les performances dépend de l'optimiseur de requêtes de base de données, mais le premier semble généralement meilleur. Et certains fournisseurs de bases de données qui n'ont pas de support natif pour le type bool peuvent générer une traduction assez inefficace ou même ne pas traduire les prédicats & / | .

Utilisez de préférence les opérateurs logiques && et || dans les requêtes LINQ.


9 commentaires

Génial! Mais je n'ai pas compris cette ligne donc elle ne peut pas être court-circuitée.


@TanvirArjel Je voulais dire, lorsqu'il est exécuté côté client, il utilise les mêmes règles d'évaluation que le code C # correspondant. par exemple. && et || court-circuiteront, & et | ne le seront pas.


J'ai compris cela! mais dans le cas d'un serveur sql expr1 ET expr2 ne se comporte pas de la même manière que C # expr1 && expr2 ? ou quoi que ce soit d'autre.


@TanvirArjel La partie court-circuit fait la différence pour l ' évaluation du client . Pour l ' évaluation du serveur , la différence réside dans la traduction SQL, qui affectera très probablement les performances en raison de conditions WHERE non naturelles.


Ma question est la suivante: dans le cas de expr1 ET expr2 dans le serveur SQL, si le premier opérande est faux, le deuxième opérande sera-t-il évalué ou non?


@TanvirArjel La façon dont la requête est évaluée dépend des optimiseurs de requêtes de base de données et des plans d'exécution de requêtes qu'ils créent. Ils sont autorisés à faire beaucoup de choses - réorganiser les conditions (afin d'utiliser l'index), etc., donc en général, vous ne pouvez pas répondre à votre question.


Je suis sur le point de voter pour votre réponse :) Une autre question: dans le cas de (expr1 & expr2) = 1 dans le serveur SQL, quel impact cela va créer dans la requête, je ne suis pas sûr à propos de ça?


@TanvirArjel Encore une fois, la façon dont la traduction SQL affecte le plan de requête est inconnue. SqlServer peut être intelligent et le traiter de la même manière que AND , ou peut-être pas. Et Oracle, par exemple, aurait certainement des problèmes de traduction et d'exécution. Le point est, AND et OR sont les manières naturelles de représenter les conditions logiques binaires à l'intérieur des prédicats SQL. L'idée de SQL est de décrire le résultat souhaité, et non comment le faire. Ce qui est différent de LINQ à Objects où l'exécution dépend de la façon dont vous composez la requête.


D'accord! Merci beaucoup, je vais les expérimenter au niveau du serveur SQL.



1
votes

J'ai décidé de faire un test:

SELECT [x].[CustomerId]
FROM [Customers] AS [x]
WHERE [x].[FirstName] IN (N'james', N'thomas')

vs

SELECT [x].[CustomerId]
FROM [Customers] AS [x]
WHERE (CASE
    WHEN [x].[FirstName] = N'james'
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END | CASE
    WHEN [x].[FirstName] = N'thomas'
    THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END) = 1

t1 a été exécuté comme:

var t2 = _db.Customers
.Where(x => x.FirstName == "james" || x.FirstName == "thomas")
.Select(x => x.CustomerId).ToList();

et t2 comme:

var t1 = _db.Customers
.Where(x => x.FirstName == "james" | x.FirstName == "thomas")
.Select(x=>x.CustomerId).ToList();

Les deux renvoient le même résultat. J'ai comparé leur plan d'exécution, pour exécuter t1 j'avais "Index Scan" tandis que pour exécuter t2 j'avais "Index Seek". Comme Justin l'a mentionné ( Plans SQL Server: différence entre l'analyse d'index / index Seek ) "Les recherches sont toujours meilleures que les analyses car elles sont plus efficaces dans la façon dont il recherche les données".

Donc, en utilisant | ou & non seulement cela peut conduire à une évaluation côté client, mais cela affectera également le SQL généré.

Merci à tous!


0 commentaires