Dynamic Linq to Entities

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
Hallo

Ik ben aan het zoeken om dynamische linq te maken (ASP.NET C# Entity Framework).
Het komt erop neer dat de where clause dus dynamisch moet worden.
Er zijn inderdaad gratis libraries te vinden om dit soort zaken te doen (bvb: LinqKit, System.Linq.Dynamic, ...)
maar vraag me af als ik echt zoiets nodig heb om het volgende te doen:

een where clause met twee 'and' blokken, waarvan het tweede bestaat uit 'or' blokjes
namelijk: condition AND (condition OR condition)

Indien iemand een menig hierover heeft, is die welkom :)

Acties:
  • 0 Henk 'm!

  • Haan
  • Registratie: Februari 2004
  • Nu online

Haan

dotnetter

Kan je een iets concreter voorbeeld geven? Want ik heb (maar dat kan ook aan mij liggen :+) nu niet echt een beeld van wat je precies probeert te bereiken.

Kater? Eerst water, de rest komt later


Acties:
  • 0 Henk 'm!

Verwijderd

SideShow schreef op vrijdag 06 januari 2012 @ 12:25:
Hallo

Ik ben aan het zoeken om dynamische linq te maken (ASP.NET C# Entity Framework).
Het komt erop neer dat de where clause dus dynamisch moet worden.
Er zijn inderdaad gratis libraries te vinden om dit soort zaken te doen (bvb: LinqKit, System.Linq.Dynamic, ...)
maar vraag me af als ik echt zoiets nodig heb om het volgende te doen:

een where clause met twee 'and' blokken, waarvan het tweede bestaat uit 'or' blokjes
namelijk: condition AND (condition OR condition)

Indien iemand een menig hierover heeft, is die welkom :)
Ja is nodig (System.Linq.Dynamic)

code:
1
2
3
4
5
        NorthwindDataContext northwind = new NorthwindDataContext();

        var query = northwind.Products
                             .Where("CategoryID = 3 AND UnitPrice > 3")
                             .OrderBy("SupplierID");

Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
Een ervaringsdeskundige ben ik ook niet, maar ik zal proberen:

Linq2Entities (een soort linq2sql eigenlijk, denk ik) voorziet dus, zoals altijd bij linq, een extension method genaamd "Where()"

Het vormt geen probleem om aan je L2E object .Where() clauses toe te voegen door middel van een for-loop... het probleem is dat deze vertaald worden naar "and" (T-SQL)

Om dus toch iets dynamischer te zijn, zijn er libraries, die functionaliteit en bijkomende extension methods, expressies, ... aanbieden om dit te kunnen doen:

bij LinqKit.dll ziet dit er zo uit:

var inner = PredicateBuilder.False<Product>();
inner = inner.Or (p => p.Description.Contains ("foo"));
inner = inner.Or (p => p.Description.Contains ("far"));
var outer = PredicateBuilder.True<Product>();
outer = outer.And (p => p.Price > 100);
outer = outer.And (p => p.Price < 1000);
outer = outer.And (inner);

Zie http://www.albahari.com/nutshell/predicatebuilder.aspx voor meer info.

Ik heb hiermee de volgende problemen:
- afhankelijkheid van een externe library om in feite iets heel eenvoudig te doen (and/or)
- onderhoudbaarheid / leesbaarheid (?)
- ikzelf ben nog maar amper intermediate kwa C# niveau en dit voelt dus niet comfortabel aan

Ik kan natuurlijk ook een plain old query schrijven ... wat onvermijdelijk leidt tot een spaghetti/mengelmoes aan sql-strings in de source code.

Acties:
  • 0 Henk 'm!

Verwijderd

Die afhankelijkheid zie ik niet als een probleem...

Dit is toch een prima en leesbare manier?(System.Linq.Dynamic)

http://weblogs.asp.net/sc...ynamic-query-library.aspx

Acties:
  • 0 Henk 'm!

  • beany
  • Registratie: Juni 2001
  • Laatst online: 06:51

beany

Meeheheheheh

SideShow schreef op vrijdag 06 januari 2012 @ 12:41:
- afhankelijkheid van een externe library om in feite iets heel eenvoudig te doen (and/or)
Blijkbaar is het dus niet zo eenvoudig en is het erg handig dat er een externe lib voor is. Punten om op te letten bij een externe lib. is: heb je de source code? is de licentie ok? kan je eventueel zelf bugs fixen? Als dit allemaal JA is, is er niks aan de hand. Een lib kopen met support is overigens ook prima(ligt aan de situatie).
- onderhoudbaarheid / leesbaarheid (?)
Niks mis met die code hoor. Dat code soms wat onnatuurlijk overkomt, komt omdat C#(en C++, Java, etc) generieke talen zijn. Dus soms moeten dingen nou eenmaal zo omdat de taal er geen verdere ondersteuning voor heeft. Wil je dit niet dan kom je al heel snel in Domain Specific Languages terecht. En dat is een heeeeeeeeel ander verhaal.
- ikzelf ben nog maar amper intermediate kwa C# niveau en dit voelt dus niet comfortabel aan
Becommentarieer je code, breek het op in stukjes(aparte methoden) en er is niks mis mee.

Dagelijkse stats bronnen: https://x.com/GeneralStaffUA en https://www.facebook.com/GeneralStaff.ua


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Geef eens een voorbeeldje van code die je zou willen schrijven hiermee. Het klinkt alsof je iets wilt doen waar een andere, betere methode voor beschikbaar is.

@beany:

die library maakt de hele leesbaarheid van linq juist stuk. Daarmee ga je juist weer in de richting van een LLBLGen-achtige predikaat definitie methode die simpelweg lelijk is en heel snel onleesbaar wordt. M.i. maakt het in dit geval wel degelijk uit.

[ Voor 46% gewijzigd door Grijze Vos op 06-01-2012 13:13 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
Grijze vos:

Ik heb de opdracht gekregen om een front-end ascx-control te voorzien van json data.
Ik heb ook een platte sqlserver-tabel gekregen met de data in.
Ik heb een webservice ter beschikking waar de json in geproduceerd/geformatteerd wordt, en iemand raadde me aan om met een .edmx file te werken en dan Linq 2 Entities te gebruiken.

Ik bevind me momenteel in een webmethod in de webservice, waar het produceren van de json triviaal is.
Enkel de data-access lukt me niet optimaal.

Voorbeeld:

var recordObjects = new LexactEntities(connectionString).LexactTable.Where(x => x.Taal == language);

Ik wil dus de where verder aanvullen met dynamische and/or zaken. Voor "and" is dit geen probleem, je kan volgens mij quasi oneindig "wheres" aanbouwen.
Or, is een ander verhaal, zo blijkt.

[ Voor 9% gewijzigd door SideShow op 06-01-2012 13:22 ]


Acties:
  • 0 Henk 'm!

  • jmzeeman
  • Registratie: April 2007
  • Laatst online: 08-09 07:36
Ben zelf niet heel erg bekend met linq to SQL maar kan je niet gewoon een Expression vullen en die gebruiken? System.Linq.Dynamic is niks anders als een parser die een string om kan zetten naar een expression object.

[ Voor 25% gewijzigd door jmzeeman op 06-01-2012 13:27 ]


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Volgens mij heb je het probleem al goed opgelost, dus wat is het probleem nu eigenlijk? ;) Afhankelijkheid van een library is alleen een probleem als je de code-size zo klein mogelijk wil houden.
Grijze Vos schreef op vrijdag 06 januari 2012 @ 13:11:
die library maakt de hele leesbaarheid van linq juist stuk. Daarmee ga je juist weer in de richting van een LLBLGen-achtige predikaat definitie methode die simpelweg lelijk is en heel snel onleesbaar wordt. M.i. maakt het in dit geval wel degelijk uit.
Hoe zou je dit anders willen doen? Voor dynamisch zoeken op A and (B or C.or ...) zonder problemen zoals sql-injectie lijkt me dit prima eigenlijk? :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
Momenteel ben ik goed op weg denk ik (met System.Linq.Dynamic):
new LexactEntities(connectionString).LexactTable.Where("Taal = @0 && Type = @1", language, type);

Aangezien de methode een params heeft in de signature, zal ik nu eindelijk dynamisch kunnen afwerken waarschijnlijk.
Met LinqKit ging ik de mist in...

Alvast bedankt aan iedereen !

*edit: mocht iemand het interessant vinden de code te lezen van een beginner ;) hierzo:

//Build where clause
var orBuilder = new StringBuilder();
for (int i = 0, j = 2; i < filters.Length; i++, j++) orBuilder.AppendFormat(" || DeelCd.Contains(@{0})", j);

var whereClause = String.Format("Taal = @0 && Type = @1 && (1 = 0{0})", orBuilder);
var connectionString = ConfigurationManager.AppSettings["LexactEntities"];
var sqlParameters = new List<object>().FluentAdd(language).FluentAdd(type).FluentAddRange(filters).ToArray();

var records = new LexactEntities(connectionString).LexactTable.Where(whereClause, sqlParameters);

Zes regels code (en dan maar even de 3000 regels code vergeten van de extra linq lib :+

[ Voor 51% gewijzigd door SideShow op 06-01-2012 16:09 ]


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
pedorus schreef op vrijdag 06 januari 2012 @ 13:27:

Hoe zou je dit anders willen doen? Voor dynamisch zoeken op A and (B or C.or ...) zonder problemen zoals sql-injectie lijkt me dit prima eigenlijk? :p
Een factory method maken die Expression<Func<T,bool>> voor een bepaalde property van een bepaald datatype terug geeft met een bepaald type vergelijking ( kleiner dan, groter dan, gelijk aan, bevat, etc.) is vrij simpel als je eenmaal weet hoe expression trees werken.

Deze daarna met LinqKit's predicate builder aan elkaar rijgen en vervolgens m.b.v. de AsExpandable() extension method aan de IQueryable toevoegen. Dat is een stuk beter afgeschermd dan dynamic LINQ.

Ik heb dit soort implementatie zelf al eens geschreven voor een set filters op een ExtJs grid. Het is zeker niet triviale code, maar is goed te doen.

Acties:
  • 0 Henk 'm!

  • Guillome
  • Registratie: Januari 2001
  • Niet online

Guillome

test

Verwijderd schreef op vrijdag 06 januari 2012 @ 12:40:
[...]


Ja is nodig (System.Linq.Dynamic)

code:
1
2
3
4
5
        NorthwindDataContext northwind = new NorthwindDataContext();

        var query = northwind.Products
                             .Where("CategoryID = 3 AND UnitPrice > 3")
                             .OrderBy("SupplierID");
Huh waarom niet:

code:
1
.Where(p => p.CategoryID = 3 && p.UnitPrice > 3).

If then else matters! - I5 12600KF, Asus Tuf GT501, Asus Tuf OC 3080, Asus Tuf Gaming H670 Pro, 48GB, Corsair RM850X PSU, SN850 1TB, Arctic Liquid Freezer 280, ASUS RT-AX1800U router


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Guillome schreef op zaterdag 07 januari 2012 @ 13:04:
[...]


Huh waarom niet:

code:
1
.Where(p => p.CategoryID = 3 && p.UnitPrice > 3).
Omdat dat niet gaat werken wanneer de veldnaam of het type vergelijking dynamisch in te vullen moet zijn.

Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 10-09 20:32
SideShow schreef op vrijdag 06 januari 2012 @ 13:45:
Momenteel ben ik goed op weg denk ik (met System.Linq.Dynamic):
new LexactEntities(connectionString).LexactTable.Where("Taal = @0 && Type = @1", language, type);

Aangezien de methode een params heeft in de signature, zal ik nu eindelijk dynamisch kunnen afwerken waarschijnlijk.
Met LinqKit ging ik de mist in...

Alvast bedankt aan iedereen !
Mag hopen dat je dat niet op die manier in je code hebt staan. Maar op zn minst zo:

C#:
1
2
3
4
using(var context = new LexactEntities(connectionString))
{
     context.LexactTable.Where("Taal = @0 && Type = @1", language, type);
}


Crux is dat je de using statement gebruikt om je verbinding automatisch te sluiten nadat je klaar bent met je werk. Ook al treed er een exception op.

Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
wordt de connection pool niet automatisch gebruikt / beheerd ?
het is asp.net

raad is welkom

ik heb het in ieder geval aangepast

[ Voor 16% gewijzigd door SideShow op 07-01-2012 23:33 ]


Acties:
  • 0 Henk 'm!

  • hostname
  • Registratie: April 2009
  • Laatst online: 10:59
SideShow schreef op vrijdag 06 januari 2012 @ 13:45:
Momenteel ben ik goed op weg denk ik (met System.Linq.Dynamic):
new LexactEntities(connectionString).LexactTable.Where("Taal = @0 && Type = @1", language, type);

Aangezien de methode een params heeft in de signature, zal ik nu eindelijk dynamisch kunnen afwerken waarschijnlijk.
Met LinqKit ging ik de mist in...

Alvast bedankt aan iedereen !

*edit: mocht iemand het interessant vinden de code te lezen van een beginner ;) hierzo:

C#:
1
2
3
4
5
6
7
8
9
//Build where clause
var orBuilder = new StringBuilder();
for (int i = 0, j = 2; i < filters.Length; i++, j++) orBuilder.AppendFormat(" || DeelCd.Contains(@{0})", j);

var whereClause = String.Format("Taal = @0 && Type = @1 && (1 = 0{0})", orBuilder);
var connectionString = ConfigurationManager.AppSettings["LexactEntities"];
var sqlParameters = new List<object>().FluentAdd(language).FluentAdd(type).FluentAddRange(filters).ToArray();

var records = new LexactEntities(connectionString).LexactTable.Where(whereClause, sqlParameters);


Zes regels code (en dan maar even de 3000 regels code vergeten van de extra linq lib :+
Volgens mij moet dit makkelijk te doen zijn zonder dynamische query (ben niet heel bekend met linq2entities, maar vanuit mijn kennis van linq2objects lijkt me wel dat dit moet werken):

C#:
1
table.Where(row => row.Taal == language && row.Type == type && filters.Any(filter => row.DeelCd.Contains(filter)));

Of iets duidelijker, met de query syntax:
C#:
1
2
3
4
from row in table
where row.Taal == language && row.Type == type &&
  filters.Any(filter => row.DeelCd.Contains(filter)
select row

Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 10-09 20:32
SideShow schreef op zaterdag 07 januari 2012 @ 23:18:
wordt de connection pool niet automatisch gebruikt / beheerd ?
het is asp.net

raad is welkom

ik heb het in ieder geval aangepast
Connection pooling is inderdaad aanwezig. Maar dat wil niet zeggen dat je je verbindingen niet moet opruimen.
Connection pooling is geen silver bullet die al je connection problemen oplost. Op het moment dat je een connection open, dan komt deze uit de pool. Op het moment dat je deze weer afsluit wordt deze weer terug gegeven aan de pool, klaar om opnieuw gebruikt te worden.

Als je je verbinding dus niet afsluit komt hij 'nooit' meer terug in de pool. waardoor je pool leegraakt, en je in het gunstigste geval geen verbindingen meer krijgt, en in het slechtste geval je je database server volslurpt met loze verbindingen, welke allemaal blijven bestaan totdat de idle timeout optreed....

maw.. altijd opruimen die hap.

Acties:
  • 0 Henk 'm!

  • SideShow
  • Registratie: Maart 2004
  • Laatst online: 16-06 15:55

SideShow

Administrator

Topicstarter
Laatste twee posters: bedankt, ik bekijk het !

Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Grijze Vos schreef op vrijdag 06 januari 2012 @ 13:11:
die library maakt de hele leesbaarheid van linq juist stuk. Daarmee ga je juist weer in de richting van een LLBLGen-achtige predikaat definitie methode die simpelweg lelijk is en heel snel onleesbaar wordt. M.i. maakt het in dit geval wel degelijk uit.
Nou nou... ZO lelijk zijn die predicates nou ook weer niet ;) ok, wel een beetje ;). Daarom is een fluent interface wellicht beter (zoals onze nieuwe QuerySpec API, zie mn blog).

Linq is vrij rigide wat dat betreft mbt dynamic queries, en Microsoft onderkent dit veel te weinig.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com

Pagina: 1