Ich versuche , um zu bestimmen , wie man zählt die passenden Zeilen auf einem Tisch die EntityFramework verwenden.
Das Problem ist, dass jede Zeile möglicherweise viele Megabyte Daten enthält (in einem Binärfeld). Natürlich wäre das SQL ungefähr so:
SELECT COUNT(*) FROM [MyTable] WHERE [fkID] = '1';
Ich könnte alle Zeilen laden und dann die Anzahl finden mit:
var owner = context.MyContainer.Where(t => t.ID == '1');
owner.MyTable.Load();
var count = owner.MyTable.Count();
Das ist aber grob ineffizient. Gibt es einen einfacheren Weg?
EDIT: Danke an alle. Ich habe die Datenbank aus einem privaten Anhang verschoben, damit ich die Profilerstellung ausführen kann. Das hilft, verursacht aber Verwirrungen, die ich nicht erwartet hatte.
Und meine realen Daten sind etwas tiefer, ich werde Lastwagen verwenden, die Paletten mit Kisten mit Gegenständen tragen - und ich möchte nicht, dass der Lastwagen verlässt, es sei denn, es ist mindestens ein Gegenstand darin.
Meine Versuche sind unten gezeigt. Der Teil, den ich nicht bekomme, ist, dass CASE_2 niemals auf den DB-Server (MSSQL) zugreift.
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
Und das aus CASE_1 resultierende SQL wird durch sp_executesql geleitet , aber:
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
[ Ich habe nicht wirklich Lastwagen, Fahrer, Paletten, Koffer oder Gegenstände; Wie Sie aus der SQL ersehen können, sind die Beziehungen zwischen LKW und Palette sowie zwischen Palette und Fall viele zu viele - obwohl ich nicht denke, dass dies wichtig ist. Meine realen Objekte sind immateriell und schwerer zu beschreiben, deshalb habe ich die Namen geändert. ]]