Comment COMPTER des lignes dans EntityFramework sans charger le contenu?

c# database entity-framework

Question

J'essaie de déterminer comment compter les lignes correspondantes sur une table à l'aide de EntityFramework.

Le problème est que chaque ligne peut contenir plusieurs mégaoctets de données (dans un champ binaire). Bien sûr, le code SQL ressemblerait à ceci:

SELECT COUNT(*) FROM [MyTable] WHERE [fkID] = '1';

Je pourrais charger toutes les lignes et ensuite trouver le compte avec:

var owner = context.MyContainer.Where(t => t.ID == '1');
owner.MyTable.Load();
var count = owner.MyTable.Count();

Mais c'est totalement inefficace. Y a-t-il un moyen plus simple?


EDIT: Merci à tous. J'ai déplacé la base de données d'un attaché privé pour pouvoir exécuter le profilage; cela aide mais provoque des confusions que je ne m'attendais pas.

Et mes données réelles étant un peu plus profondes, je vais utiliser des camions transportant des palettes de caisses d’ objets - et je ne veux pas que le camion quitte la pièce à moins qu’il ne contient au moins un article .

Mes tentatives sont indiquées ci-dessous. La partie que je ne comprends pas, c'est que CASE_2 n'a jamais accès au serveur de base de données (MSSQL).

var truck = context.Truck.FirstOrDefault(t => (t.ID == truckID));
if (truck == null)
    return "Invalid Truck ID: " + truckID;
var dlist = from t in ve.Truck
    where t.ID == truckID
    select t.Driver;
if (dlist.Count() == 0)
    return "No Driver for this Truck";

var plist = from t in ve.Truck where t.ID == truckID
    from r in t.Pallet select r;
if (plist.Count() == 0)
    return "No Pallets are in this Truck";
#if CASE_1
/// This works fine (using 'plist'):
var list1 = from r in plist
    from c in r.Case
    from i in c.Item
    select i;
if (list1.Count() == 0)
    return "No Items are in the Truck";
#endif

#if CASE_2
/// This never executes any SQL on the server.
var list2 = from r in truck.Pallet
        from c in r.Case
        from i in c.Item
        select i;
bool ok = (list.Count() > 0);
if (!ok)
    return "No Items are in the Truck";
#endif

#if CASE_3
/// Forced loading also works, as stated in the OP...
bool ok = false;
foreach (var pallet in truck.Pallet) {
    pallet.Case.Load();
    foreach (var kase in pallet.Case) {
        kase.Item.Load();
        var item = kase.Item.FirstOrDefault();
        if (item != null) {
            ok = true;
            break;
        }
    }
    if (ok) break;
}
if (!ok)
    return "No Items are in the Truck";
#endif

Et le SQL résultant de CASE_1 est acheminé via sp_executesql , mais:

SELECT [Project1].[C1] AS [C1]
FROM   ( SELECT cast(1 as bit) AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN  (SELECT 
    [GroupBy1].[A1] AS [C1]
    FROM ( SELECT 
        COUNT(cast(1 as bit)) AS [A1]
        FROM   [dbo].[PalletTruckMap] AS [Extent1]
        INNER JOIN [dbo].[PalletCaseMap] AS [Extent2] ON [Extent1].[PalletID] = [Extent2].[PalletID]
        INNER JOIN [dbo].[Item] AS [Extent3] ON [Extent2].[CaseID] = [Extent3].[CaseID]
        WHERE [Extent1].[TruckID] = '....'
    )  AS [GroupBy1] ) AS [Project1] ON 1 = 1

[ Je n'ai pas vraiment de camions, de chauffeurs, de palettes, de caisses ou d'objets; Comme vous pouvez le constater d'après le code SQL, les relations camion-palette et palette-caisse sont multiples - bien que, selon moi, cela ne compte pas. Mes vrais objets sont intangibles et plus difficiles à décrire, alors j'ai changé les noms. ]

Réponse acceptée

Syntaxe de la requête:

var count = (from o in context.MyContainer
             where o.ID == '1'
             from t in o.MyTable
             select t).Count();

Syntaxe de la méthode:

var count = context.MyContainer
            .Where(o => o.ID == '1')
            .SelectMany(o => o.MyTable)
            .Count()

Les deux génèrent la même requête SQL.


Réponse populaire

Je pense que tu veux quelque chose comme

var count = context.MyTable.Count(t => t.MyContainer.ID == '1');

(édité pour refléter les commentaires)



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow