Laden...

WCF Methode mit dynamischem Where Statement ?

Erstellt von KroaX vor 11 Jahren Letzter Beitrag vor 11 Jahren 2.616 Views
KroaX Themenstarter:in
301 Beiträge seit 2009
vor 11 Jahren
WCF Methode mit dynamischem Where Statement ?

Hallo zusammen,

vorab : Datenbanksystem SQL Server 2008 R2
Mapper : Entity Framework 4.3.1 mit Selftracking Entities

ich konzipiere grade eine Anwendung die auch auf Methoden eines WCF Services zugreift.

Meine Anwendung selbst ist nicht an eine Datenbank angebunden und empfängt EntityObjekte lediglich über die Methoden des Services. Abfragen an die Datenbank möchte ich dennoch relativ dynamisch gestalten und nicht für jede Filtermöglichkeit einen weiteren Parameter hinzufügen. Sprich : Ich möchte ein where Statement von der Anwendung an den WCF Service übergeben, der diesen an die eigentliche LINQ Abfrage anheftet.

Mein erster Gedanke dazu war, dass ich einfach eine Expression als Parameter übergebe. Diesen Gedanken musste ich aber verwerfen, da Expressions nicht serialisierbar sind. Es gibt zwar eine Bibliothek die es angeblich ermöglichen soll, jedoch ist diese einige Jahre alt, privat entwickelt ( ggf. verbuggt ) und Werte als Parameter aus Objekten heraus führen wohl zu Fehlern.

Ich hatte mich also von dem Gedanken der Expressions verabschiedet und mich mit dem Gedanken angefreundet einen string zu übergeben, der ein Where Statement darstellt zu übergeben. Ich las einiges über dynamic linq, was mir prinzipiell gefiel auch wenn diese in Form von strings an das Linqstatement übergeben werden.

Bsp : Dynamic LINQ (Part 1: Using the LINQ Dynamic Query Library)

Prinzipiell würde ich diese Methode auch nutzen, allerdings nur dann wenn man aus dem Code heraus solche Statements generieren könnte und nicht selbst strings schreiben muss. Dazu hatte ich mir den PredicateBuilder angeschaut ( PredicateBuilder) allerdings scheint dieser nicht das zu realisieren was ich eigentlich möchte.

Kennt jemand von euch möglicherweise ein geeignetes Framework für mein Vorhaben oder hat jemand anderes noch eine Idee wie ich dies umsetzen kann? Ggf. würde ich auch nochmal in die Serialisierung von Expressions reinschauen, da mir dieser Ansatz vom Prinzip her am besten gefallen würde.

Jede Idee würde mir weiterhelfen

J
641 Beiträge seit 2007
vor 11 Jahren

cSharp Projekte : https://github.com/jogibear9988

KroaX Themenstarter:in
301 Beiträge seit 2009
vor 11 Jahren

Ähm ... ich glaube du hast gar nicht gelesen was ich geschrieben habe oder ?

D
91 Beiträge seit 2005
vor 11 Jahren

Ich freue mich schon auf Antworten!

Vor genau dem selben Problem stehe ich gerade auch. OK, das mit der Serialisierbarkeit habe ich nicht, aber auch ich muss eine Abfrage dynamisch zur Laufzeit anhand persistierter Parameter erstellen. Etwas richtig intelligentes ist mir auch nicht eingefallen, außer die Dynamic-LINQ library. Bin mal gespannt, ob jemand einen eleganteren Weg kennt, außer die magic-strings von Hand zu erstellen.

2.891 Beiträge seit 2004
vor 11 Jahren

Hast du dir mal WCF Data Services angeguckt?

Da werden auf Server-Seite ein IQueryable-Dingens bereit gestellt und können dann auf dem Client mit (etwas eingeschränkten) LINQ-Ausdrücken abgefragt werden. Die Übertragung der Ausdrücke geschieht dann via OData-Protokoll. Also an sich ja genau das, was du möchtest, oder?

Ein Einführungs-Video von SHanselman gibt's unter OData Basics.

KroaX Themenstarter:in
301 Beiträge seit 2009
vor 11 Jahren

Ja diesen Service kenne ich. Allerdings möchte ich schon bei meinem eigenen Service bleiben und nicht meine ganze Datenbank nach außen veröffentlichen. Interessant wäre also lediglich wie der Service intern funktioniert und diese Art und weise in meinem Service zu adaptieren.

2.891 Beiträge seit 2004
vor 11 Jahren

Allerdings möchte ich schon bei meinem eigenen Service bleiben und nicht meine ganze Datenbank nach außen veröffentlichen.

Du musst damit ja nicht die DB veröffentlichen. Was du als IQueryable bereit stellst, kannst du ja völlig frei entscheiden. Das kann ja auch nur irgendeine Objekt-Liste sein.

KroaX Themenstarter:in
301 Beiträge seit 2009
vor 11 Jahren

So wie ich das gelesen habe kann man bei diesen Services immer nur eine untergeordnete Entitytabelle als Datasource angeben und diese wird dann vollständig freigegeben ( + Berechtigungen )

Im Prinzip würde dies ja vielleicht sogar ( zumindest zur Abfrage ) doch in Frage kommen. Ich denke gerade daran diese Services zur Abfrage von Daten zu nutzen (Read only), und sämtliche andere Datenoperationen in einem eigenen Service zu implementieren.

Ob das in Frage kommt entscheidet jedoch ob man bei der Datenabfrage auch das Include Statement vom Entity Framework nutzen kann.

Außerdem ist es entscheidend, dass ich meine definierten Self Tracking Entities erhalte und diese auch an den anderen ( selbst geschrieben ) Service weiterreichen kann ( dies sollte auf Grund von Typen wiederverwendung aus Assembly XY bei erstellung des Clientproxys mMn aber eigentlich abgedeckt sein.

Ich muss mich da heute nach Feierabend mal durcharbeiten

EDIT : Grade gefunden. Include scheint sogar zu gehen, dass macht den Einsatz für mich nun doch recht wahrscheinlich Referenz

6.911 Beiträge seit 2009
vor 11 Jahren

Hallo KroaX,

sollte es sich bei den Clients nur um Silverlight-Anwendungen handeln, so würde ich die RIA Services verwenden. Dort könntest du auch schauen wie das mit den "Expression" serialisiert wird.

Um bei den Clients jedoch keine Einschränkung zu haben, ist oData bzw. die WCF Dataservices die korrekte Wahl.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

KroaX Themenstarter:in
301 Beiträge seit 2009
vor 11 Jahren

Hallo gfoidl,

es soll sich um unterschiedliche Anwendungen handeln die Zugriff haben. Ich hatte daher zunächst den Ansatz einen RIA Service zu verwenden bin jedoch dann auch darauf gestoßen, dass man dort nicht oder nur eingeschränkt auf OData Abfragen zugreifen kann.

Daher habe ich nun doch die OData Schnittstelle eingesetzt ( bzw. bin noch dabei das umzusetzen ). Meine Struktur habe ich auch verändert und habe den EntityContext jetzt im Webprojekt wo auch mein Dataservice liegt.

Dieser wird dann von einer Library referenziert und die konsumierten objekte werden dort um zusätzliche Properties und ggf. Funktionen erweitert. ( Modellayer )

Eine weitere Library ( DataLayer ) greift auf den Modellayer zu und stellt dann Repositories ( jedes Repository hat eine eigene ServiceClientInstanz ) für jede Anwendung zur Verfügung, die diese Library referenziert.

In meinem Fall wäre dass dann zunächst eine WPF Anwendung und später noch eine Website

Passt so ganz gut von der Aufteilung oder ?

6.911 Beiträge seit 2009
vor 11 Jahren

Hallo KroaX,

stellt dann Repositories ( jedes Repository hat eine eigene ServiceClientInstanz )

Meinst du damit, dass die Repositories auf Client-Seite sind? Sonst würde ich die Repos. auf der Server-Seite anbieten - wie im angehängten Bild. Jeder große Kasten stellt dabei ein Projekt dar.

Bei den Clients erstelle ich meist auch eine eigenes Projekt für den Service und die Anwendung (wie bei WPF) referenziert dann dieses Client-Projekt. So sind die einzelnen Teile leichter wartbar und ggf. austauschbar.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

3.728 Beiträge seit 2005
vor 11 Jahren
InterLinq

Hallo KroaX,

ich glaube was Du suchst ist InterLinq.
Damit kannst Du Linq-Abfragen über WCF oder .NET Remoting serialisieren.

Als Autor der Kommunikationskomponente Zyan möchte ich an der Stelle auch ein bischen Eigenwerbung machen. Zyan serialisiert LINQ-Abfragen out-of-the-box.

Beispiel:


// Service-Schnittstelle
interface ISampleService
{
	IEnumerable<T> GetList<T>() where T : class;

	IQueryable<T> Query<T>() where T : class;
}

// Vom Client aus Verbindung zum Applikationsserver herstellen herstellen
using (var connection = new ZyanConnection("tcpex://localhost/myappserver"))
{
        // Verbindung zum Service herstellen
	var proxy = connection.CreateProxy<ISampleService>();
	
        // LINQ-Abfrage direkt auf den Service machen
        var query =
	    from c in proxy.Query<Customer>()
	    where c.BirthDate > DateTime.Today.AddYears(-18)
	    select c;
	...
}

Die Customer-Klasse im Beispiel muss natürlich serialisierbar sein.
Wenn Du interoperabel sein musst, also Dein Client kein .NET Client (min. .NET Client Profile wird benötigt) ist, dann ist Zyan leider nicht geeignet. Zyan macht innerhalb der schönen .NET-Welt alles in Sachen RPC sehr einfach, kann aber nicht Kaffeebohnen, Telefonen, Toastern, etc. reden. Wenn Letztere auf Deiner Client-Liste stehen, nimm WCF und probier mal InterLinq aus.

Gruß
Rainbird

KroaX Themenstarter:in
301 Beiträge seit 2009
vor 11 Jahren

Hallo Rainbird,

das klingt ganz interessant. Ich bin aber mittlerweile auf den WCF Dataservice Zug aufgesprungen. Vielleicht werde ich mir das mal anschauen wenn ich etwas Zeit habe =)