Linq to Entities-Gruppe Durch (ÄUßERE GELTEN) "oracle 11.2.0.3.0 nicht unterstützt gelten"
Ich habe das code sample unten, welche Abfragen eine Liste der Produkte.
var productResults = Products.Where((p) => refFilterSequence.Contains(p.Ref))
.GroupBy(g => g.Code, (key, g) => g.OrderBy(whp => whp.Ref).First()).ToList();
Dies funktioniert genau wie erwartet und gibt die 4 Zeilen möchte ich bei Verwendung einer in-memory Sammlung, aber beim laufen gegen die Oracle-Datenbank:
.GroupBy(g => g.Code, (key, g) => g.OrderBy(whp => whp.Ref).First())
Löst dies ein Fehler zu sagen, die ich verwenden sollte FirstOrDefault
nicht unterstützt werden in einer Oracle-Datenbank. Der Fehler oracle 11.2.0.3.0 nicht unterstützt gelten geworfen erhält. Googleing, offenbart auf CodePlex: https://entityframework.codeplex.com/workitem/910.
Dies tritt, wenn die folgenden Binärdateien:
- EntityFramework 6.0.0.0
- Oracle.ManagedDataAccess 4.121.2.0
- Oracle.ManagedDataAccess.EntityFramework 6.121.2.0
- .Net Framework 4.5.1
Die Datenbank ist eine Oracle 11.2.0.3.0 Datenbank.
Generierte sql verwendet OUTER APPLY (siehe Bild unten), das nicht unterstützt wird von der 11.2.0.3.0 von der Oracle-version so, warum ist EF/Oracle.ManagedDataAccess versucht, es zu benutzen? Gibt es eine Möglichkeit zu sagen, das EF nicht zu benutzen, die ANZUWENDEN keyword?
Dieser Seite weiter unten sagt, dass die GELTEN-Unterstützung in Oracle 12c Release 1, aber ich kann nicht aktualisieren, alle meine Datenbanken nur eine GRUPPE machen, die VON der Arbeit.
http://www.oracle.com/technetwork/database/windows/newfeatures-084113.html
Scheint es, dass dies ein bekanntes Problem (Bekannte Probleme in SqlClient für Entity Framework):
Im folgenden werden einige typische Szenarien können dazu führen, dass die
Vorhandensein von CROSS APPLY-und/oder OUTER APPLY-Operatoren in der Ausgabe
Abfrage:
- LINQ-Abfragen, die Gruppierung der Methoden akzeptieren, dass ein element-Selektor.
Bevor ich Sie resort zum erstellen einer Ansicht (hätte ich eine Ansicht erstellen, die auf mehrere Datenbanken), kann jemand sehen, noch eine andere Lösung?
Für alle interessierten, die SQL -, die tun, was ich will, gegen diese Datenbank version würde in etwa wie folgt Aussehen:
select *
from ( select RANK() OVER (PARTITION BY sm.product ORDER BY refs.map) ranking, sm.*
from schema.table sm,
(
select 'R9' ref, 0 map from dual
union all
select 'R1' ref, 1 map from dual
union all
select 'R6' ref, 2 map from dual
) refs
where sm.ref= refs.ref
) stock
where ranking = 1
Wird der code schließlich in eine service-Klasse übergeben und die OData-controller in Web-API.
Das Beispiel unten verwendet die demo-Daten, die eigentliche Datenbank hat rund 700.000 Datensätze,
so möchte ich vermeiden, der die Abfrage ausführt und lassen OData Griff Seite Grenzen und weiter filtern.
using System;
using System.Collections.Generic;
using System.Linq;
namespace DemoApp
{
class Program
{
public class Product
{
public string Ref { get; set; }
public string Code { get; set; }
public int Quantity { get; set; }
}
//demo data
static readonly List<Product> Products = new List<Product>
{
new Product { Ref = "B2", Code = "ITEM1", Quantity = 1},
new Product { Ref = "R1", Code = "ITEM1", Quantity = 2},
new Product { Ref = "R9", Code = "ITEM1", Quantity = 3},
new Product { Ref = "R9", Code = "ITEM2", Quantity = 4},
new Product { Ref = "R6", Code = "ITEM2", Quantity = 5},
new Product { Ref = "B2", Code = "ITEM3", Quantity = 6},
new Product { Ref = "R1", Code = "ITEM3", Quantity = 7},
new Product { Ref = "R9", Code = "ITEM3", Quantity = 8},
new Product { Ref = "B2", Code = "ITEM4", Quantity = 9},
new Product { Ref = "X3", Code = "ITEM4", Quantity = 10},
new Product { Ref = "B8", Code = "ITEM5", Quantity = 10},
new Product { Ref = "R6", Code = "ITEM5", Quantity = 12},
new Product { Ref = "M2", Code = "ITEM5", Quantity = 13},
new Product { Ref = "R1", Code = "ITEM5", Quantity = 14},
};
static void Main(string[] args)
{
//this array is of variable length, and will not always contain 3 items.
var refFilterSequence = new List<string> {"R9", "R1", "R6"};
var results = GetProductsForODataProcessing(refFilterSequence);
//some further filtering may occur after the queryable is returned.
//the actual implmentation is an OData Web API, so filters, expansions etc could be added.
//results = results.Where(p => p.Quantity > 2);
results.ToList().ForEach(p => Console.WriteLine("RANK:{0}\tREF:{1}\tCode:{2}\tQty:{3}", "?", p.Ref, p.Code, p.Quantity));
Console.ReadLine();
}
static IQueryable<Product> GetProductsForODataProcessing(List<string> filterSequence )
{
var productResults = Products.Where((p) => filterSequence.Contains(p.Ref))
.GroupBy(g => g.Code, (key, g) => g.OrderBy(whp => whp.Ref).First()).AsQueryable();
return productResults;
}
}
//Example Output
//.......................
//REF:R1 Code:ITEM1 Qty:2
//REF:R6 Code:ITEM2 Qty:3
//REF:R1 Code:ITEM3 Qty:7
//REF:R1 Code:ITEM5 Qty:14
Du musst angemeldet sein, um einen Kommentar abzugeben.
Seit Sie schreiben konnte, die Abfrage selbst. Vielleicht können Sie eine gespeicherte Prozedur erstellen, mit dem Sie es und rufen den SP von Entity Framework.
Können Sie versuchen, ausführen von ToArray vor der GroupBy -, so führt er in Erinnerung. Es wird nicht die optimale Leistung, aber sollte funktionieren.
Oracle 11 unterstützt nicht GELTEN. Oracle-12 jedoch.