You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
publicclassVariance {} //This class won't be used for this part.
189
189
190
190
//Add this classes/interfaces in a seperate file or place it somewhere you like.
191
191
192
192
```
193
193
194
-
Hier komt later wat uitleg.
194
+
Hierboven is de layout voor #contravariantie en #covariantie. Schrik niet. Ik zal precies uitleggen wat het nou eigenlijk is. We maken 2 #interface en #class aan. In IProducer passen we #covariantie toe. Dit geven we expliciet met het keyword #out. Je kunt het zien als argument is uit de method en als return type. #T heeft een return type met waarde #T.
195
+
196
+
Daarna laten we #class Producer inheriten van IProducer. Beide hebben de #generics waarde van #T. Voor #T returnen we #default. Dit zet alle waardes op #null of de absolute 0 waarde wanneer dit van toepassing is. Dan hebben we een #interface IConsumer. Hier passen we #contravariantie toe. Met het keyword #in maak je #T expliciet #contravariant.
197
+
198
+
Je ziet dat we geen return type hebben. Wel hebben we een obj argument van type #T. #in is als argument in de method. Dit is van laag naar hoog, #contravariantie is van hoog naar laag. Vervolgens hebben we een #class Consumer met type #T als #generics type. Daarna implementeren we de method met argument obj van type #T. We zetten hier onze #code.
199
+
200
+
> We zetten daar het volgende in: #Console.WriteLine($"This contravariance returns: {obj}.\n");
201
+
202
+
### #Contravariance and #Covariance Result
195
203
196
204
```C#
197
205
namespaceConsoleApp1;
@@ -214,7 +222,116 @@ public class Program
214
222
215
223
```
216
224
217
-
> Het volgende resultaat is: This contravariance returns: h.
225
+
We roepen het programma aan met de #interface en maken twee objecten aan. Hierboven zie je #Covariance en #Contravariance in actie. Het is duidelijk wat het resultaat is van deze code.
226
+
227
+
> Het volgende resultaat is: This #contravariance returns: h.
228
+
229
+
### #Contravariance and #Covariance Example 2
230
+
231
+
We maken een super simpel programma. 2 #class met eentje genaamd: Base en de andere genaamd: Derived. Deze inherited van Base. Beide #class hebben hun eigen method, die iets uitprinten in de #Console . In Program hebben we ook 2 methods die we gebruiken voor de #Action. In de uitleg in de #code kun je precies zien hoe dit nou eigenlijk te werk gaat.
232
+
233
+
```C#
234
+
namespaceConsoleApp1;
235
+
236
+
publicclassBase
237
+
{
238
+
publicvoidPrintBase()
239
+
{
240
+
Console.WriteLine("Base");
241
+
}
242
+
}
243
+
244
+
publicclassDerived : Base
245
+
{
246
+
publicvoidPrintDerived()
247
+
{
248
+
Console.WriteLine("Derived");
249
+
}
250
+
}
251
+
252
+
publicclassProgram
253
+
{
254
+
privatestaticvoidPrintActionBase(Baseb)
255
+
{
256
+
Console.WriteLine("Action Base");
257
+
}
258
+
259
+
privatestaticvoidPrintActionDerived(Derivedd)
260
+
{
261
+
Console.WriteLine("Action Derive");
262
+
}
263
+
264
+
publicstaticvoidMain()
265
+
{
266
+
varbase1=newBase(); //Invariant met implicit typing
267
+
Derivedderived1=new(); //Invariant met new() object
268
+
269
+
objectBasebase2=newDerived(); //Covariant, hoog naar laag
270
+
Derivedderived2=newBase(); //Contravariant, laag naar hoog
271
+
272
+
List<Base>base3=newList<Derived>(); //Covariant, hoog naar laag
273
+
List<Derived>derived3=newList<Base>(); //Contravariant, laag naar hoog
274
+
275
+
IEnumerable<Base>base4=newList<Derived>(); //Covariant, werkt met een type dat hoger is. //In dit geval de IEnumerable. Interfaces kunnen alleen voor de eerste komen te staan.
276
+
IEnumerable<Derived>derived4=newList<Base>(); //Contravariant, werkt niet met een type dat lager is, je krijgt //hierop een error. Type 'Base' doesn't match expected type 'Derived'.
277
+
278
+
Action<Base>base5=newAction<Derived>(PrintActionDerived); //Covariant, werkt niet met een type dat hoger is. Je krijgt hierop een error.
279
+
Action<Derived>derived5=newAction<Base>(PrintActionBase); //Contravariant, werkt met eem type dat lager is. In dit geval de Action. Interfaces kunnen alleen voor de eerste komen te staan.
280
+
}
281
+
}
282
+
283
+
```
284
+
285
+
> Hierboven staat in het Nederlands uitgelegd, wat #covariantie en #contravariantie nou doen.
286
+
287
+
### #Contravariance and #Covariance Example 3
288
+
289
+
Hier zullen we de boven genoemde voorbeelden nog verder verduidelijken. We maken 2 #interface en #class aan en doen daar iets mee. IGalaxy en Planet zijn #covariant. IPlanet en Orbit zijn #contravariant. We zullen met #object en #string werken. Let goed op de keywords: #out en #in. In de #code staat in het Nederlands beschreven hoe dit allemaal te werk gaat.
290
+
291
+
```C#
292
+
namespaceConsoleApp1;
293
+
294
+
publicinterfaceIGalaxy<outT> //Covariance, keyword => out, want type T is uit de argument list.
295
+
{
296
+
publicT? Covariance(); //Return type T
297
+
}
298
+
299
+
publicclassPlanet : IGalaxy<string> //Verander dit van string naar object en het return type ook, wat merk je op?
300
+
{
301
+
publicstringCovariance() =>"Planet"; //Return type
302
+
}
303
+
304
+
publicinterfaceIPlanet<inT> //Contravariance, keyword => in, want type T is in de argument list.
305
+
{
306
+
publicvoidContravariance(Tobj); //Argument type T
307
+
}
308
+
309
+
publicclassOrbit : IPlanet<object> //Verander dit van object naar string en het argument type ook, wat merk je op?
310
+
{
311
+
publicvoidContravariance(objectobj) =>Console.WriteLine(obj); //Argument type
312
+
}
313
+
314
+
publicclassProgram
315
+
{
316
+
publicstaticvoidMain()
317
+
{
318
+
//Allemaal high to low, maar:
319
+
320
+
IGalaxy<object>galaxy=newPlanet(); //Het is covariant, kijk naar de type tussen <>. Ik kan object erin stoppen en
321
+
//vervangen met string. Dit werkt, want object is een collectie die de string in zich heeft. Dit werkt.
322
+
IGalaxy<string>extraGalaxy=newPlanet(); //Invariant type werkt ook.
323
+
//IGalaxy<string> g = new Planet(); //Contravariant werkt niet hierop. string kan niet naar object. Zie regel 8/10.
324
+
325
+
IPlanet<string>planet=newOrbit(); //Het is Contravariant, kijk naar de type tussen <>. Ik kan string erin stoppen
326
+
//en vervangen met object. Dit werkt, want string behoort tot een collectie die vanuit object komt. Dit werkt.
327
+
IPlanet<object>extraplanet=newOrbit(); //Invariant type werkt ook.
328
+
//IPlanet<object> p = new Orbit(); //Covariant werkt niet hierop. object kan niet naar string. Zie regel 18/20.
329
+
}
330
+
}
331
+
332
+
```
333
+
334
+
> Hierboven staat in het Nederlands uitgelegd, wat #covariantie en #contravariantie nou doen.
Copy file name to clipboardExpand all lines: notes_wpfw/csharp/wpfw_deel1/week2/testen_mocks.md
+6
Original file line number
Diff line number
Diff line change
@@ -50,6 +50,12 @@ We maken een #interface ICalculator met een #generics met type #T. Daaraan geven
50
50
51
51
Nadat we de Mock hebben, maken we een #class / #struct met de daadwerkelijke implementatie. We maken een Calculator en in de #Primary-Constructor geven we de #interface mee met iCalculator argument. Dit is #Dependency-Injection . Je implementeert niet de #interface, maar geeft dit als waarde mee.
52
52
53
+
> Hier is hoe #Primary-Constructor werkt met #Dependency-Injection :
De MockCalculator die de #interface implementeert is #Dependency-Inversion. Terug naar Calculator. De argument die meegegeven is een #interface-Injection en de #Property een #setter-Injection. Die is #readonly en #private. We willen niet de Mock implementatie aanroepen. Je ziet ook een #generics constraint met where #T : #INumber #T.
54
60
55
61
Nu is het alleen mogelijk om arithmatic getallen eraan mee te geven. Als laatste hebben we de twee methods die we in de test gaan gebruiken. De implementatie lijkt bijna hetzelfde als de #interface , maar we kunnen de namen van die method voor de => aanpassen. Voor het gemak laten we het zoals het is. #generics types zijn optioneel. Het is geen requirement voor een Mock.
Copy file name to clipboardExpand all lines: notes_wpfw/csharp/wpfw_deel1/week4/orm_en_linq.md
+75-6
Original file line number
Diff line number
Diff line change
@@ -347,23 +347,88 @@ public class Program
347
347
348
348
```
349
349
350
-
## ORM
350
+
## #ORM
351
351
352
-
Dit wordt later beschreven.
352
+
#ORM staat voor Object Relational Mapping en zorgt ervoor dat je data kan aansturen van en naar Databases. Het maakt de vertaalslag naar queries, zodat je niet dit zelf hoeft te schrijven. Terwijl je focust op de datastructuren, doet het #ORM de rest voor je. Hieronder staat een goeie uitleg van #ChatGPT die in het Engels is geschreven.
353
+
354
+
> Het gaat over wat een #ORM precies oplost en tegen welke problemen je kan aanlopen.
355
+
356
+
**ChatGPT**
357
+
**Object-Relational Mapping (ORM)** is a programming technique that allows data to be seamlessly transferred between an object-oriented system and a relational database system. The main problems that #ORM aims to solve are related to the impedance mismatch between the object-oriented programming paradigm and the relational database model.
358
+
359
+
### Problems #ORM Solves:
360
+
361
+
1.**Impedance Mismatch:**
362
+
363
+
-**Problem:** Object-oriented languages (like Java or C#) represent data using objects, while relational databases store data in tables. The differences between these models create an impedance mismatch.
364
+
-**Solution:** #ORM provides a way to map objects to database tables and vice versa, helping to bridge the gap between the object-oriented and relational worlds.
365
+
2.**Boilerplate Code:**
366
+
367
+
-**Problem:** Manually writing SQL queries and mapping database results to objects can be tedious and error-prone, leading to a lot of boilerplate code.
368
+
-**Solution:** #ORM tools automate the process of #CRUD (Create, Read, Update, Delete) operations, reducing the amount of boilerplate #code and improving developer productivity.
369
+
3.**Database Abstraction:**
370
+
371
+
-**Problem:** Without #ORM, developers need to write code specific to the database they are using. Switching databases can be challenging.
372
+
-**Solution:** #ORM abstracts away the underlying database details, making it easier to switch between different database systems without major code changes.
373
+
4.**Maintainability:**
374
+
375
+
-**Problem:** When the data model changes, manual updates to SQL queries and #object mappings are required, making maintenance challenging.
376
+
-**Solution:** #ORM tools often provide automated schema generation and migration tools, making it easier to adapt to changes in the data model.
377
+
378
+
### Problems Encountered with #ORM:
379
+
380
+
1.**Performance Overhead:**
381
+
382
+
-**Issue:** #ORM tools may introduce performance overhead compared to hand-tuned SQL queries, especially for complex or performance-critical applications.
383
+
-**Mitigation:** #ORM tools often provide ways to optimize queries, and developers can choose to use native SQL queries when necessary.
384
+
2.**Learning Curve:**
385
+
386
+
-**Issue:** There can be a learning curve associated with understanding and effectively using an #ORM, especially for developers new to the tool.
387
+
-**Mitigation:** Training, documentation, and experience can help developers become proficient with the #ORM tool.
388
+
3.**Customization Limitations:**
389
+
390
+
-**Issue:** Some #ORMs might limit the flexibility to perform highly customized or optimized database operations.
391
+
-**Mitigation:** Some #ORM tools provide ways to write custom queries or use native SQL when needed, but it depends on the specific #ORM.
392
+
4.**Mapping Complex Relationships:**
393
+
394
+
-**Issue:** Mapping complex relationships between objects and database tables can be challenging and may require additional configuration.
395
+
-**Mitigation:** #ORMs often provide features and annotations to handle complex relationships, but developers need to be aware of and properly configure these.
396
+
397
+
While #ORM tools can greatly simplify database interaction in many scenarios, it's important to be aware of their limitations and potential issues. The choice to use an #ORM should be based on the specific requirements and constraints of the project.
353
398
354
399
## Explicit, Eager and Lazy #Loading
355
400
356
-
#Loading is een proces dat geldt voor de Entity Framework (EF) en de omliggende data in het ORM. Welke #Loading je moet gebruiken en welke sneller is aan de #usecase en wat je ermee wilt bereiken. Hieronder zullen alle verschillende #Loading worden beschreven. Omdat dit een best uitgebreid stuk kan zijn, zullen we de #code uit de docs gebruiken en niet zelf aanmaken.
401
+
#Loading is een proces dat geldt voor de Entity Framework (EF) en de omliggende data in het #ORM. Welke #Loading je moet gebruiken en welke sneller is aan de #usecase en wat je ermee wilt bereiken. Hieronder zullen alle verschillende #Loading worden beschreven. Omdat dit een best uitgebreid stuk kan zijn, zullen we de #code uit de docs gebruiken en niet zelf aanmaken.
357
402
358
403
> Url behorend tot de #code voorbeelden: https://blog.jetbrains.com/dotnet/2023/09/21/eager-lazy-and-explicit-loading-with-entity-framework-core/ en https://dzone.com/articles/working-with-lazy-loading-and-eager-loading-in-ent
359
404
360
405
### Explicit #Loading
361
406
362
-
Explicit #Loading is het proces.
407
+
Explicit #Loading is het proces waar de gegevens worden geladen wanneer je dit specifiek doet. De data wordt alleen opgehaald wanneer dit nodig is. Doe je dit niet? Dan krijg je een lege #collection . Het wordt duidelijk waar de #code voor de query wordt aangeroepen, maar je hebt nog steeds het resultaat + 1 probleem. Hieronder is een voorbeeld van Explicit #Loading .
408
+
409
+
```C#
410
+
varinvoices=db.Invoices
411
+
.ToList();
412
+
413
+
// All invoices are already loaded...
414
+
foreach (varinvoiceininvoices)
415
+
{
416
+
// ...but you'll have to explicitly load invoice lines when they are needed
> Om Explicit #Loading toe te passen, gebruik je het keyword #Load. Zie het voorbeeld hier.
363
428
364
429
## Eager #Loading
365
430
366
-
Eager #Loading is het proces waarop je op een query aanroept en daarboven op de gerelateerde gegevens en die ermee laad. Dit kun je doen met de #Include keyword. Eager #Loading is het tegenovergestelde van Lazy #Loading , want je laad meteen alle gegevens in. Dit kan voor een grote overhead zorgen. Hieronder is een voorbeeld hoe je #Loading kunt toepassen.
431
+
Eager #Loading is het proces waarop je op een query iets aanroept en daarboven op de gerelateerde gegevens ermee laad. Dit kun je doen met de #Include keyword. Eager #Loading is het niet het tegenovergestelde van Lazy #Loading , je laad wel meteen alle gegevens in. Dit kan voor een overhead zorgen. Hieronder is een voorbeeld hoe je #Loading kunt toepassen.
367
432
368
433
```C#
369
434
varinvoices=db.Invoices
@@ -397,7 +462,7 @@ using (var context = new AdventureWorksContext())
397
462
398
463
## Lazy #Loading
399
464
400
-
Lazy #Loading is het proces waarbij de query automatisch worden geladen wanneer dit nodig is. Alleen de nodige gegevens die je verwacht worden geladen. In tegenstelling tot Eager #Loading is Lazy #Loading veel sneller. Dit komt, omdat je niet expliciet aangeeft dat je hierop ook een call wilt doen.
465
+
Lazy #Loading is het proces waarbij de query automatisch worden geladen wanneer dit nodig is. Alleen de nodige gegevens die je verwacht worden geladen. In tegenstelling tot Eager #Loading is Lazy #Loading niet perse veel sneller. Je krijgt het volledige resultaat + 1. In het meeste gevallen is het niet aan te raden om dit te gebruiken. Kijk naar de benaming: Lazy.
401
466
402
467
```C#
403
468
varinvoices=db.Invoices
@@ -438,3 +503,7 @@ public sealed class NorthwindModelOptimized: NorthwindModel
438
503
}
439
504
440
505
```
506
+
507
+
### Explicit, Eager and Lazy #Loading Video
508
+
509
+
> Hier een video: https://www.youtube.com/watch?v=T9fTFynqvCw
0 commit comments