2010-05-10 13 views
5

Gibt es eine gute Möglichkeit, EdmFunctionAttribute zu nutzen, ohne eine Abhängigkeit von The Entity Framework/System.Data.Entity.dll einzuführen?Verwenden Sie EdmFunctionAttribute, ohne Entity Framework-Abhängigkeits-/Implementierungsdetails anzuzeigen?

Ich dachte, ich könnte eine Schnittstelle mit einer Methode und einer konkreten Implementierung haben, die die Methode implementiert, die EdmFunctionAttribute verwendet, um es einer Datenbankfunktion zuzuordnen.

Ich habe eine Kontextschnittstelle IMyContext in einer Baugruppe und einem Entity Framework Implementierung MyContext in einer anderen Baugruppe definiert.

public interface IMyContext 
{ 
    double SomeFunction(double first, double second); 

    // other interface details here 
} 

public partial class MyContext : IMyContext 
{ 
    [EdmFunction("MyNamespace", "MyDatabaseFunction")] 
    public double SomeFunction(double first, double second) 
    { 
     throw new NotSupportedException("This method may only be called as part of a LINQ expression."); 
    } 

    // rest of interface implementation here 
} 

Ich benutze eine Fabrik (mit StructureMap hinter den Kulissen) eine Kontextinstanz als Interface-Typ zu erhalten:

using (IMyContext context = ContextFactory.GetNewContext()) 
{ 
    var results = context.Table.Select(t => context.SomeFunction(t.Col1, t.Col2)).ToList(); 
} 

Dies wirft ein NotSupportException sagen, dass LINQ to Entities erkennen nicht die Methode ' Doppelte SomeFunction (Double, Double) '.

Wenn ich den Kontext der konkreten Umsetzung werfen

using (MyContext context = ContextFactory.GetNewContext() as MyContext) 
{ 
    ... 
} 

dann funktioniert es, aber dann bin ich verpflichtet, die konkrete Umsetzung zu spezifizieren, die ich will nicht zu tun.

Die Funktion muss kein Mitglied der Context-Klasse sein, ich habe es nur zum Erkunden dort gegeben.

+0

Ich bin mit der gleichen Situation konfrontiert. Ich hatte auch gehofft, dass das EdmFunctionAttribute aufgelöst werden würde, wenn über eine Schnittstellenreferenz zugegriffen wird, aber ohne Erfolg. Beim Arbeiten mit mehreren Kontexten (mehrere Datenbanken) wird es noch schwieriger. – kdawg

+0

Für was es wert ist, konnte ich dieses Problem nicht lösen und musste die DB-Funktion auf die konkrete Implementierung meines Repository (Kontext in Ihrem Fall) schlagen, was bedeutet, dass alle Funktionsaufrufe innerhalb meiner Repository-Klasse liegen müssen - dh: mein Client-Code konnte nicht direkt darauf zugreifen. Ich bin nicht begeistert davon, aber es funktioniert (und es erzwingt die Abfrage von Code im Repository, die einige argumentieren, ist, wo es gehört). – kdawg

Antwort

0

dies nicht möglich ist, wie Query Builder Linq die Interface-Typ und nicht die konkrete Klasse untersuchen. Der Ausdrucksbaum enthält die Methodenreferenz der Methode der Schnittstelle, und wenn Sie die Attribute der Methode untersuchen, werden keine Attribute zurückgegeben.

Sie können einen Expression-Besucher erstellen und Ihren Ausdrucksbaum besuchen und den Typ von der Schnittstelle in den konkreten Typ ändern.

TypeReplacer tr = new TypeReplacer(); 
tr.Visit(ex); 

class TypeReplacer: ExpressionVisitor{ 
    protected override MethodCallExpression MethodCall(MethodCallExpression exp) 
    { 
     // compare exp.Method and 
     // replace it with concrete Type's method 
     return exp; 
    } 
} 
+0

Entschuldigung, deine Antwort löst nichts, was in der Frage noch nicht implementiert war. Ihre Lösung erfordert weiterhin einen Verweis auf die konkrete Kontextklasse anstelle der Kontextschnittstelle. – GWB

+0

Ich habe meine Antwort aktualisiert. –

Verwandte Themen