title
Repository Pattern with C# and Entity Framework, Done Right | Mosh

description
🔥Get the COMPLETE Entity Framework course (80% OFF - LIMITED TIME): http://bit.ly/2rZAgrD Want to learn more from me? Check out my these links: Courses: https://codewithmosh.com Blog: https://www.programmingwithmosh.com/ Facebook: https://www.facebook.com/programmingwithmosh Twitter: https://twitter.com/moshhamedani Confused about the repository pattern? This tutorial explains it all. There are many tutorials about the repository pattern and many of them are conflicting. If you've been confused about the proper way to implement the repository and unit of work patterns with Entity Framework, this video is for you. 00:00 What is the Repository Pattern? 00:47 Benefits of the Repository Pattern 03:50 Repository in a Nutshell 04:47 What is the Unit of Work Pattern? 05:00 Does Entity Framework Really Implement Repository and Unit of Work Patterns? 09:31 Clean Architecture 11:43 Implementing the Repository Pattern 14:09 Implementing the Unit of Work Pattern 15:09 Repository and Unit of Work Patterns in Code 22:49 Example of Repository and Unit of Work Patterns Download the source code for this video here: http://programmingwithmosh.com/wp-content/uploads/2015/10/RepositoryPattern.zip And here are some YouTube videos of mine you might be interested in: Event and Delegates in C# https://youtu.be/jQgwEsJISy0?list=PLTjRvDozrdlz3_FPXwb6lX_HoGXa09Yef Generics https://youtu.be/gyal6TbgmSU?list=PLTjRvDozrdlz3_FPXwb6lX_HoGXa09Yef

detail
{'title': 'Repository Pattern with C# and Entity Framework, Done Right | Mosh', 'heatmap': [{'end': 776.604, 'start': 755.438, 'weight': 0.704}, {'end': 855.821, 'start': 835.755, 'weight': 0.771}, {'end': 935.864, 'start': 900.478, 'weight': 0.789}, {'end': 1045.648, 'start': 996.8, 'weight': 1}, {'end': 1180.41, 'start': 1058.673, 'weight': 0.792}, {'end': 1284.386, 'start': 1235.049, 'weight': 0.763}, {'end': 1315.892, 'start': 1297.956, 'weight': 0.774}], 'summary': "Mosh's video covers repository pattern, its benefits, and misconceptions, emphasizing decoupling applications, exploring persistence frameworks, and clean architecture principles. it also delves into implementing repository and unit of work patterns with entity framework, focusing on creating generic repository interfaces and efficient data access.", 'chapters': [{'end': 103.01, 'segs': [{'end': 56.14, 'src': 'embed', 'start': 21.656, 'weight': 2, 'content': [{'end': 24.459, 'text': 'and address some of the misconceptions about repositories.', 'start': 21.656, 'duration': 2.803}, {'end': 33.466, 'text': "So what is the repository pattern? I'm going to start with a definition from Martin Fowler's book, Patterns of Enterprise Application Architecture.", 'start': 25.5, 'duration': 7.966}, {'end': 41.811, 'text': 'Repository mediates between the domain and data mapping layers, acting like an in-memory collection of domain objects.', 'start': 34.726, 'duration': 7.085}, {'end': 46.414, 'text': "I've highlighted in-memory collection in this phrase because that's the key here.", 'start': 42.671, 'duration': 3.743}, {'end': 56.14, 'text': "So what are the benefits of the repository pattern? The first one, again based on Martin Fowler's book, is that it minimizes duplicate query logic.", 'start': 47.414, 'duration': 8.726}], 'summary': 'Repository pattern mediates between domain and data layers, minimizing duplicate query logic.', 'duration': 34.484, 'max_score': 21.656, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM21656.jpg'}, {'end': 103.01, 'src': 'embed', 'start': 65.227, 'weight': 0, 'content': [{'end': 70.628, 'text': "Without the repository pattern, we'll end up duplicating this query logic over and over in different places.", 'start': 65.227, 'duration': 5.401}, {'end': 79.51, 'text': 'In situations like this, we can encapsulate this logic in a repository and simply call a method like getTopSellingCourses,', 'start': 71.688, 'duration': 7.822}, {'end': 83.51, 'text': 'which takes two parameters the category and the number of courses to return.', 'start': 79.51, 'duration': 4}, {'end': 86.691, 'text': 'So this is one benefit of the pattern.', 'start': 84.791, 'duration': 1.9}, {'end': 94.767, 'text': 'Another benefit of the repository pattern is that it decouples your application from persistence frameworks, in this case entity framework.', 'start': 87.785, 'duration': 6.982}, {'end': 103.01, 'text': 'So in the future, if you decide to switch to a different persistence framework, you can do so with minimal impact on the rest of your application.', 'start': 95.707, 'duration': 7.303}], 'summary': 'Repository pattern avoids duplicating query logic, decouples from persistence frameworks.', 'duration': 37.783, 'max_score': 65.227, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM65227.jpg'}], 'start': 2.381, 'title': 'Repository pattern demystified', 'summary': "Clarifies the repository pattern, its benefits, and addresses misconceptions while emphasizing its role in minimizing duplicate query logic and decoupling applications from persistence frameworks, with examples from martin fowler's book.", 'chapters': [{'end': 103.01, 'start': 2.381, 'title': 'Repository pattern demystified', 'summary': "Clarifies the repository pattern, its benefits, and addresses misconceptions while emphasizing its role in minimizing duplicate query logic and decoupling applications from persistence frameworks, with examples from martin fowler's book.", 'duration': 100.629, 'highlights': ['The repository pattern minimizes duplicate query logic by encapsulating the logic in a repository, reducing code duplication and increasing maintainability.', 'The repository pattern decouples applications from persistence frameworks, allowing for easier switching to a different persistence framework with minimal impact on the rest of the application.', "The repository pattern acts like an in-memory collection of domain objects, mediating between the domain and data mapping layers, as defined by Martin Fowler's book, Patterns of Enterprise Application Architecture."]}], 'duration': 100.629, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM2381.jpg', 'highlights': ['The repository pattern minimizes duplicate query logic by encapsulating the logic in a repository, reducing code duplication and increasing maintainability.', 'The repository pattern decouples applications from persistence frameworks, allowing for easier switching to a different persistence framework with minimal impact on the rest of the application.', "The repository pattern acts like an in-memory collection of domain objects, mediating between the domain and data mapping layers, as defined by Martin Fowler's book, Patterns of Enterprise Application Architecture."]}, {'end': 692.576, 'segs': [{'end': 146.036, 'src': 'embed', 'start': 120.036, 'weight': 1, 'content': [{'end': 127.181, 'text': "application architectures are so tangled and tightly coupled to any framework that it doesn't give us the freedom to change it.", 'start': 120.036, 'duration': 7.145}, {'end': 133.666, 'text': 'A while ago, I read somewhere on a blog that on average, every two years, we get a new persistence framework.', 'start': 128.021, 'duration': 5.645}, {'end': 135.027, 'text': "And I think that's very true.", 'start': 133.966, 'duration': 1.061}, {'end': 137.088, 'text': 'First, we had ADO.NET.', 'start': 135.687, 'duration': 1.401}, {'end': 141.171, 'text': 'So we used SQL connection and SQL command to access the database.', 'start': 137.688, 'duration': 3.483}, {'end': 146.036, 'text': "Then Link to SQL came along, but it didn't prove to be successful.", 'start': 142.193, 'duration': 3.843}], 'summary': 'Application architectures are tightly coupled to frameworks, with a new persistence framework every two years on average.', 'duration': 26, 'max_score': 120.036, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM120036.jpg'}, {'end': 228.122, 'src': 'embed', 'start': 187.622, 'weight': 0, 'content': [{'end': 193.846, 'text': 'And if you want to have the freedom to explore a different persistence framework with minimal impact in your application,', 'start': 187.622, 'duration': 6.224}, {'end': 195.947, 'text': "that's when you should use the repository pattern.", 'start': 193.846, 'duration': 2.101}, {'end': 201.095, 'text': 'Now there is also another benefit with the repository pattern that some claim.', 'start': 197.352, 'duration': 3.743}, {'end': 204.177, 'text': 'That it makes it easier to unit test your application.', 'start': 201.916, 'duration': 2.261}, {'end': 205.979, 'text': "But that's partially true.", 'start': 204.978, 'duration': 1.001}, {'end': 211.503, 'text': "And that's if you're using an older version of Entity Framework with Object Context and Object Set.", 'start': 206.719, 'duration': 4.784}, {'end': 218.048, 'text': 'The new DbContext and DbSet objects have interfaces that you can mock to unit test your applications.', 'start': 212.544, 'duration': 5.504}, {'end': 222.712, 'text': "So you don't necessarily need the repository pattern to unit test your application.", 'start': 218.889, 'duration': 3.823}, {'end': 228.122, 'text': 'Now, the theory behind what is the repository in practice.', 'start': 224.861, 'duration': 3.261}], 'summary': 'Repository pattern allows exploring new frameworks with minimal impact and aids in unit testing, but not always necessary with newer entity framework versions.', 'duration': 40.5, 'max_score': 187.622, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM187622.jpg'}, {'end': 303.236, 'src': 'embed', 'start': 272.745, 'weight': 5, 'content': [{'end': 273.525, 'text': 'Now with this.', 'start': 272.745, 'duration': 0.78}, {'end': 278.567, 'text': "the first question that pops into a lot of people's head, including myself a long time ago,", 'start': 273.525, 'duration': 5.042}, {'end': 286.95, 'text': 'is if the repository acts as a collection of objects in memory, how are we going to save these objects and changes to them to the database?', 'start': 278.567, 'duration': 8.383}, {'end': 290.572, 'text': "That's when the unit of work pattern comes in the picture.", 'start': 287.871, 'duration': 2.701}, {'end': 299.055, 'text': 'A unit of work maintains a list of objects affected by a business transaction and coordinates the writing out of changes.', 'start': 291.852, 'duration': 7.203}, {'end': 303.236, 'text': 'this is where things get interesting.', 'start': 300.954, 'duration': 2.282}], 'summary': 'Unit of work pattern coordinates changes for saving objects to database.', 'duration': 30.491, 'max_score': 272.745, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM272745.jpg'}, {'end': 395.139, 'src': 'embed', 'start': 366.412, 'weight': 3, 'content': [{'end': 371.973, 'text': 'So it will coordinate persisting changes across multiple repositories in one transaction.', 'start': 366.412, 'duration': 5.561}, {'end': 381.315, 'text': 'So on the surface, yes, entity framework DB sets and DB context indeed look like repositories and unit of work.', 'start': 373.433, 'duration': 7.882}, {'end': 387.157, 'text': 'But there is a hidden problem here with the implementation of these patterns in entity framework.', 'start': 382.616, 'duration': 4.541}, {'end': 395.139, 'text': "Let's review the benefits of the repository pattern again and see if our DB sets satisfy the definition of repositories.", 'start': 388.317, 'duration': 6.822}], 'summary': 'Entity framework coordinates changes across repositories in one transaction.', 'duration': 28.727, 'max_score': 366.412, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM366412.jpg'}, {'end': 634.483, 'src': 'embed', 'start': 602.078, 'weight': 2, 'content': [{'end': 605.34, 'text': 'Now the theory aside, I want you to think like an engineer.', 'start': 602.078, 'duration': 3.262}, {'end': 607.942, 'text': 'Be pragmatic, keep it simple.', 'start': 606.161, 'duration': 1.781}, {'end': 613.026, 'text': 'My favorite quote is that simplicity is the ultimate sophistication.', 'start': 608.803, 'duration': 4.223}, {'end': 620.491, 'text': "Just adhering to clean architecture principles and using all sorts of patterns doesn't necessarily make you a better coder.", 'start': 614.025, 'duration': 6.466}, {'end': 623.373, 'text': 'Neither does it improve the quality of your software.', 'start': 621.371, 'duration': 2.002}, {'end': 628.037, 'text': 'Not every application needs sophisticated architecture like this.', 'start': 624.634, 'duration': 3.403}, {'end': 634.483, 'text': 'A lot of times you might be building simple or proof of concept applications for a limited audience.', 'start': 629.098, 'duration': 5.385}], 'summary': "Think pragmatically, prioritize simplicity. sophisticated architecture isn't always necessary for every application.", 'duration': 32.405, 'max_score': 602.078, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM602078.jpg'}], 'start': 104.07, 'title': 'Evolution of persistence frameworks and repository pattern', 'summary': 'Discusses the evolution of persistence frameworks and the repository pattern, emphasizing the need for the repository pattern to explore different persistence frameworks with minimal impact and its role in facilitating unit testing. it also compares the implementation of the repository pattern and unit of work in entity framework with ideal architectural benefits and highlights the importance of adhering to clean architecture principles while being pragmatic.', 'chapters': [{'end': 228.122, 'start': 104.07, 'title': 'Changing persistence frameworks', 'summary': 'Discusses the evolution of persistence frameworks, emphasizing the need for the repository pattern to facilitate the exploration of different persistence frameworks with minimal impact and its partial role in facilitating unit testing.', 'duration': 124.052, 'highlights': ['The average frequency of a new persistence framework is every two years, with examples including ADO.NET, Link to SQL, Entity Framework, Enhybernet, and newer frameworks like Dapper, ORM Lite, and Petapokos.', 'The repository pattern provides the freedom to explore different persistence frameworks with minimal impact on the application.', 'The repository pattern plays a partial role in facilitating unit testing, especially with older versions of Entity Framework with Object Context and Object Set.']}, {'end': 692.576, 'start': 229.143, 'title': 'Repository pattern and unit of work', 'summary': 'Discusses the repository pattern and unit of work, comparing their implementation in entity framework with the ideal architectural benefits, highlighting issues with the db sets and context and emphasizing the importance of adhering to clean architecture principles while also being pragmatic.', 'duration': 463.433, 'highlights': ['The repository pattern should resemble a collection of objects in memory and should not have methods like update and save, while the unit of work pattern coordinates the writing out of changes, addressing the need to save objects and changes to the database. Repository pattern should resemble a collection of objects in memory, unit of work coordinates writing out of changes.', "Entity Framework's DB sets and context seemingly implement the repository and unit of work patterns, but there are hidden issues, such as the lack of architectural benefits like minimizing duplicate query logic and decoupling the application from persistence frameworks. Entity Framework's DB sets and context seemingly implement patterns but lack architectural benefits like minimizing duplicate query logic and decoupling the application from persistence frameworks.", 'Adherence to clean architecture principles is emphasized, with a pragmatic approach recommended, advocating for simplicity and the use of patterns only when necessary, rather than as a means to improve software quality without understanding the problem at hand. Emphasizing adherence to clean architecture principles, advocating for simplicity and pragmatic use of patterns.']}], 'duration': 588.506, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM104070.jpg', 'highlights': ['The repository pattern provides the freedom to explore different persistence frameworks with minimal impact on the application.', 'The average frequency of a new persistence framework is every two years, with examples including ADO.NET, Link to SQL, Entity Framework, Enhybernet, and newer frameworks like Dapper, ORM Lite, and Petapokos.', 'Adherence to clean architecture principles is emphasized, with a pragmatic approach recommended, advocating for simplicity and the use of patterns only when necessary, rather than as a means to improve software quality without understanding the problem at hand.', "Entity Framework's DB sets and context seemingly implement the repository and unit of work patterns, but there are hidden issues, such as the lack of architectural benefits like minimizing duplicate query logic and decoupling the application from persistence frameworks.", 'The repository pattern plays a partial role in facilitating unit testing, especially with older versions of Entity Framework with Object Context and Object Set.', 'The repository pattern should resemble a collection of objects in memory and should not have methods like update and save, while the unit of work pattern coordinates the writing out of changes, addressing the need to save objects and changes to the database. Repository pattern should resemble a collection of objects in memory, unit of work coordinates writing out of changes.']}, {'end': 998.861, 'segs': [{'end': 743.644, 'src': 'embed', 'start': 693.68, 'weight': 0, 'content': [{'end': 698.804, 'text': 'Now in the next lecture, I will show you how to implement the repository and unit of work patterns with entity framework.', 'start': 693.68, 'duration': 5.124}, {'end': 701.266, 'text': 'I hope you enjoyed this lecture and thank you for watching.', 'start': 699.364, 'duration': 1.902}, {'end': 707.671, 'text': "All right, now let's see how we can implement the repository pattern with entity framework.", 'start': 703.748, 'duration': 3.923}, {'end': 713.235, 'text': "First, I'm going to show you a diagram of the interfaces and classes, and then we'll explore the code.", 'start': 708.412, 'duration': 4.823}, {'end': 717.499, 'text': 'So to start with, we need a repository interface.', 'start': 714.436, 'duration': 3.063}, {'end': 722.683, 'text': 'This interface is like the interface for a collection of objects in memory.', 'start': 718.7, 'duration': 3.983}, {'end': 728.49, 'text': 'so it has methods like add, remove, get and find.', 'start': 723.646, 'duration': 4.844}, {'end': 732.454, 'text': "again here we're not going to have update or safe.", 'start': 728.49, 'duration': 3.964}, {'end': 737.478, 'text': "next, we're going to implement this interface in a class called repository.", 'start': 732.454, 'duration': 5.024}, {'end': 743.644, 'text': "inside this repository we're going to have a DB context, a generic DB context.", 'start': 737.478, 'duration': 6.166}], 'summary': 'Implementation of repository and unit of work patterns with entity framework, using a repository interface and a class called repository.', 'duration': 49.964, 'max_score': 693.68, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM693680.jpg'}, {'end': 788.93, 'src': 'heatmap', 'start': 755.438, 'weight': 0.704, 'content': [{'end': 760.62, 'text': "In context of our application, Pluto, for each entity, we're gonna have a repository.", 'start': 755.438, 'duration': 5.182}, {'end': 766.143, 'text': "So for course entity, we're gonna have an interface called iCourseRepository.", 'start': 761.881, 'duration': 4.262}, {'end': 775.067, 'text': "In this interface, we're gonna define any operations specific to courses that are not in our generic repository.", 'start': 767.744, 'duration': 7.323}, {'end': 776.604, 'text': 'for example,', 'start': 776.084, 'duration': 0.52}, {'end': 788.93, 'text': 'we can have a method like get top selling courses or another method get courses with authors which uses eager loading to load the courses and their authors.', 'start': 776.604, 'duration': 12.326}], 'summary': 'In the pluto application, each entity will have a repository with specific operations, like get top selling courses and get courses with authors.', 'duration': 33.492, 'max_score': 755.438, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM755438.jpg'}, {'end': 862.031, 'src': 'heatmap', 'start': 835.755, 'weight': 0.771, 'content': [{'end': 840.297, 'text': 'But it also additionally implements I course repository interface.', 'start': 835.755, 'duration': 4.542}, {'end': 844.998, 'text': "So it's going to have implementations for these two methods you see on the right side.", 'start': 841.477, 'duration': 3.521}, {'end': 848.359, 'text': 'Next, unit of work.', 'start': 847.019, 'duration': 1.34}, {'end': 852.28, 'text': 'So we need an interface like I unit of work.', 'start': 849.819, 'duration': 2.461}, {'end': 855.821, 'text': 'This interface is specific to our application.', 'start': 853.14, 'duration': 2.681}, {'end': 862.031, 'text': "So it's going to expose various repositories based on the entities we have in our application.", 'start': 857.028, 'duration': 5.003}], 'summary': 'Implements i course repository and i unit of work interfaces.', 'duration': 26.276, 'max_score': 835.755, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM835755.jpg'}, {'end': 933.141, 'src': 'embed', 'start': 900.478, 'weight': 1, 'content': [{'end': 903.8, 'text': "I'm going to take you through every interface and their implementation,", 'start': 900.478, 'duration': 3.322}, {'end': 908.162, 'text': 'but you can also download all the source code and the supplementary materials of this lecture.', 'start': 903.8, 'duration': 4.362}, {'end': 910.504, 'text': "Let's start with IRepository.", 'start': 908.863, 'duration': 1.641}, {'end': 917.268, 'text': "Okay, here's my IRepository interface.", 'start': 915.287, 'duration': 1.981}, {'end': 924.634, 'text': 'know that this is a generic interface where T entity is a class.', 'start': 918.188, 'duration': 6.446}, {'end': 933.141, 'text': 'some developers like to have a marker interface like I entity and decorate their domain classes like course, author tag,', 'start': 924.634, 'duration': 8.507}], 'summary': 'Overview of irepository interface and its generic implementation', 'duration': 32.663, 'max_score': 900.478, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM900478.jpg'}, {'end': 935.864, 'src': 'heatmap', 'start': 900.478, 'weight': 0.789, 'content': [{'end': 903.8, 'text': "I'm going to take you through every interface and their implementation,", 'start': 900.478, 'duration': 3.322}, {'end': 908.162, 'text': 'but you can also download all the source code and the supplementary materials of this lecture.', 'start': 903.8, 'duration': 4.362}, {'end': 910.504, 'text': "Let's start with IRepository.", 'start': 908.863, 'duration': 1.641}, {'end': 917.268, 'text': "Okay, here's my IRepository interface.", 'start': 915.287, 'duration': 1.981}, {'end': 924.634, 'text': 'know that this is a generic interface where T entity is a class.', 'start': 918.188, 'duration': 6.446}, {'end': 933.141, 'text': 'some developers like to have a marker interface like I entity and decorate their domain classes like course, author tag,', 'start': 924.634, 'duration': 8.507}, {'end': 935.864, 'text': 'cover and so on with that interface.', 'start': 933.141, 'duration': 2.723}], 'summary': 'Overview of irepository interface and its generic implementation', 'duration': 35.386, 'max_score': 900.478, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM900478.jpg'}], 'start': 693.68, 'title': 'Implementing repository and unit of work patterns', 'summary': 'Discusses the implementation of the repository and unit of work patterns with entity framework, focusing on creating generic repository interfaces, implementing specific interfaces for entities, and defining methods for finding, adding, and removing objects within the repository.', 'chapters': [{'end': 998.861, 'start': 693.68, 'title': 'Implementing repository and unit of work patterns', 'summary': 'Discusses the implementation of the repository and unit of work patterns with entity framework, focusing on creating generic repository interfaces, implementing specific interfaces for entities, and defining methods for finding, adding, and removing objects within the repository.', 'duration': 305.181, 'highlights': ['The chapter discusses the implementation of the repository and unit of work patterns with entity framework The lecture covers the implementation of repository and unit of work patterns specifically with entity framework, providing a practical approach to working with data access concerns and business logic.', 'Creating generic repository interfaces and implementing specific interfaces for entities The chapter explains the need for repository interfaces and their generic nature, along with the implementation of specific interfaces for entities like iCourseRepository and iAuthorRepository, allowing for tailored operations for each entity.', 'Defining methods for finding, adding, and removing objects within the repository The chapter details the methods within the repository interface, such as get, getAll, find, add, add range, remove, and remove range, providing a comprehensive overview of the available operations for managing objects within the repository.']}], 'duration': 305.181, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM693680.jpg', 'highlights': ['The chapter details the methods within the repository interface, such as get, getAll, find, add, add range, remove, and remove range, providing a comprehensive overview of the available operations for managing objects within the repository.', 'Creating generic repository interfaces and implementing specific interfaces for entities The chapter explains the need for repository interfaces and their generic nature, along with the implementation of specific interfaces for entities like iCourseRepository and iAuthorRepository, allowing for tailored operations for each entity.', 'The chapter discusses the implementation of the repository and unit of work patterns with entity framework, providing a practical approach to working with data access concerns and business logic.']}, {'end': 1574.108, 'segs': [{'end': 1180.41, 'src': 'heatmap', 'start': 1035.945, 'weight': 0, 'content': [{'end': 1038.165, 'text': 'This method returns IEnumerable.', 'start': 1035.945, 'duration': 2.22}, {'end': 1040.627, 'text': "It doesn't return IQueryable.", 'start': 1038.867, 'duration': 1.76}, {'end': 1042.268, 'text': "And that's the key thing here.", 'start': 1041.227, 'duration': 1.041}, {'end': 1045.648, 'text': 'Your repositories should not return IQueryable.', 'start': 1042.887, 'duration': 2.761}, {'end': 1053.711, 'text': 'Because this can give the wrong impression to the upper layers, like services or controllers, that they can use this IQueryable to build queries.', 'start': 1046.449, 'duration': 7.262}, {'end': 1058.032, 'text': 'Which is completely against the idea of using a repository in the first place.', 'start': 1054.451, 'duration': 3.581}, {'end': 1063.054, 'text': 'Your repositories should encapsulate your queries, so you do not repeat them.', 'start': 1058.673, 'duration': 4.381}, {'end': 1069.375, 'text': 'So here in getAll, I simply call toList to return an IEnumerable.', 'start': 1064.892, 'duration': 4.483}, {'end': 1080.221, 'text': 'The implementation of other methods like find, add, addRange is pretty similar to using a normal DB context to adding objects or removing them.', 'start': 1070.635, 'duration': 9.586}, {'end': 1083.162, 'text': 'So nothing special here.', 'start': 1081.982, 'duration': 1.18}, {'end': 1086.604, 'text': 'Again, you can download the source code and study it on your own.', 'start': 1083.763, 'duration': 2.841}, {'end': 1091.287, 'text': 'So note that this IRepository and its implementation are completely generic.', 'start': 1087.825, 'duration': 3.462}, {'end': 1093.148, 'text': 'They got nothing to do with our application.', 'start': 1091.487, 'duration': 1.661}, {'end': 1096.337, 'text': "Now let's take a look at a custom repository.", 'start': 1094.315, 'duration': 2.022}, {'end': 1099.479, 'text': "So I'm going to show you iCourseRepository.", 'start': 1097.257, 'duration': 2.222}, {'end': 1108.686, 'text': 'So this interface derives from our generic repository interface.', 'start': 1104.263, 'duration': 4.423}, {'end': 1115.352, 'text': "So it's going to inherit all those generic operations like add, add range, remove, get, and so on.", 'start': 1109.487, 'duration': 5.865}, {'end': 1123.378, 'text': 'But it also declares two additional operations, getTopSellingCourses and getCoursesWithAuthors.', 'start': 1116.192, 'duration': 7.186}, {'end': 1127.877, 'text': 'Again, note that both these methods return IEnumerable.', 'start': 1124.915, 'duration': 2.962}, {'end': 1133.101, 'text': "So we're going to execute the query inside the repository and return a list of objects to the client.", 'start': 1128.557, 'duration': 4.544}, {'end': 1136.423, 'text': "Now let's take a look at the implementation of this interface.", 'start': 1134.121, 'duration': 2.302}, {'end': 1148.971, 'text': "So this class courseRepository derives from our generic repository, because we don't want to repeat all that code for adding,", 'start': 1140.245, 'duration': 8.726}, {'end': 1151.033, 'text': 'removing and getting objects from the repository.', 'start': 1148.971, 'duration': 2.062}, {'end': 1158.02, 'text': 'So it inherits from repository of course, And also implement high course repository.', 'start': 1152.153, 'duration': 5.867}, {'end': 1162.442, 'text': "So here's the implementation of the methods in this interface.", 'start': 1159.141, 'duration': 3.301}, {'end': 1169.905, 'text': 'Now get top selling courses does not really have the actual implementation of getting top selling courses.', 'start': 1164.403, 'duration': 5.502}, {'end': 1180.41, 'text': "All I'm doing here for simplicity is ordering courses by their full price and getting the first few most expensive courses.", 'start': 1170.385, 'duration': 10.025}], 'summary': 'Repositories should return ienumerable, not iqueryable. custom repository implements additional operations like gettopsellingcourses and getcourseswithauthors.', 'duration': 79.407, 'max_score': 1035.945, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM1035944.jpg'}, {'end': 1228.688, 'src': 'embed', 'start': 1189.976, 'weight': 3, 'content': [{'end': 1193.157, 'text': 'This method uses eager loading to load courses and their authors.', 'start': 1189.976, 'duration': 3.181}, {'end': 1199.998, 'text': 'So we start with courses, then include authors, then order by, skip, and take.', 'start': 1193.877, 'duration': 6.121}, {'end': 1204.399, 'text': 'This is for paging because we have supplied a page index and a page size.', 'start': 1200.398, 'duration': 4.001}, {'end': 1208.2, 'text': 'So this is another technique that you can use with repositories.', 'start': 1205.32, 'duration': 2.88}, {'end': 1215.542, 'text': 'Some developers think they have to use iQueryable so that they can apply filtering in the upper layers like services or controllers.', 'start': 1208.96, 'duration': 6.582}, {'end': 1219.686, 'text': "But your filtering for pages shouldn't happen in those layers.", 'start': 1216.886, 'duration': 2.8}, {'end': 1223.007, 'text': "It's data access code and should happen inside your repositories.", 'start': 1219.947, 'duration': 3.06}, {'end': 1228.688, 'text': 'So the way to do that is by passing two parameters here, page index and page size.', 'start': 1224.307, 'duration': 4.381}], 'summary': 'Eager loading method for paging: load courses with authors, order, skip, and take using repositories, not upper layers.', 'duration': 38.712, 'max_score': 1189.976, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM1189976.jpg'}, {'end': 1291.331, 'src': 'heatmap', 'start': 1235.049, 'weight': 5, 'content': [{'end': 1236.67, 'text': 'Like page size is 10 by default.', 'start': 1235.049, 'duration': 1.621}, {'end': 1241.27, 'text': 'Now here I have declared a property for simplicity.', 'start': 1238.17, 'duration': 3.1}, {'end': 1244.991, 'text': 'This property is of type PlutoContext.', 'start': 1243.131, 'duration': 1.86}, {'end': 1254.646, 'text': 'So all I am doing is casting the context that we are inheriting from the generic repository, the base of this class.', 'start': 1246.738, 'duration': 7.908}, {'end': 1256.507, 'text': "we're casting that to Pluto context.", 'start': 1254.646, 'duration': 1.861}, {'end': 1260.351, 'text': 'Otherwise, in every method here, I had to repeat this code.', 'start': 1257.629, 'duration': 2.722}, {'end': 1265.436, 'text': 'Cast the context first and then get access to the courses DB set.', 'start': 1261.793, 'duration': 3.643}, {'end': 1269.3, 'text': "Now let's take a look at the unit of work.", 'start': 1267.838, 'duration': 1.462}, {'end': 1277.14, 'text': "So here's my IUnitOfWork interface.", 'start': 1275.339, 'duration': 1.801}, {'end': 1284.386, 'text': 'Note that it inherits from IDisposable and exposes two repositories.', 'start': 1278.401, 'duration': 5.985}, {'end': 1287.048, 'text': 'CourseRepository and AuthorRepository.', 'start': 1285.186, 'duration': 1.862}, {'end': 1289.45, 'text': 'And note that both these are interfaces.', 'start': 1287.748, 'duration': 1.702}, {'end': 1291.331, 'text': 'This is for testability.', 'start': 1290.29, 'duration': 1.041}], 'summary': 'Default page size is 10. plutocontext property declared for simplicity. iunitofwork interface inherits from idisposable and exposes two repositories: courserepository and authorrepository.', 'duration': 33.702, 'max_score': 1235.049, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM1235049.jpg'}, {'end': 1336.713, 'src': 'heatmap', 'start': 1297.956, 'weight': 0.774, 'content': [{'end': 1299.177, 'text': "And here's my complete method.", 'start': 1297.956, 'duration': 1.221}, {'end': 1302.019, 'text': "Let's take a look at the implementation.", 'start': 1300.638, 'duration': 1.381}, {'end': 1309.066, 'text': 'So this unit of work, as I said, is specific to our application.', 'start': 1305.563, 'duration': 3.503}, {'end': 1315.892, 'text': 'So it receives Pluto context in the constructor and store it in a private field here.', 'start': 1310.047, 'duration': 5.845}, {'end': 1318.534, 'text': 'And this is the interesting part.', 'start': 1317.353, 'duration': 1.181}, {'end': 1324.56, 'text': 'It uses the same context to initialize both repositories.', 'start': 1320.456, 'duration': 4.104}, {'end': 1336.713, 'text': "So the client of unit of work will instantiate a Pluto context And then we'll use this context across all repositories.", 'start': 1326.721, 'duration': 9.992}], 'summary': 'Unit of work method uses pluto context to initialize both repositories.', 'duration': 38.757, 'max_score': 1297.956, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM1297956.jpg'}], 'start': 1000.148, 'title': 'Repository implementation and unit of work', 'summary': 'Discusses repository implementation, emphasizing ienumerable over iqueryable, and illustrates custom repository creation. it also introduces unit of work, explaining methods like ordering courses and eager loading with paging, aiming for testable and efficient data access.', 'chapters': [{'end': 1162.442, 'start': 1000.148, 'title': 'Repository implementation and custom repository', 'summary': 'Discusses the generic implementation of a repository, emphasizing the importance of returning ienumerable instead of iqueryable to encapsulate queries, and illustrates the creation and implementation of a custom repository interface and class inheriting from the generic repository.', 'duration': 162.294, 'highlights': ['The importance of repositories not returning IQueryable is emphasized, as it can give the wrong impression to upper layers, like services or controllers, that they can use this IQueryable to build queries, which is against the idea of using a repository (quantifiable: emphasizes the return of IEnumerable instead of IQueryable to encapsulate queries).', 'The concept of encapsulating queries within repositories to avoid repetition is highlighted, with the getAll method demonstrating the use of toList to return an IEnumerable (quantifiable: emphasizes the encapsulation of queries within repositories to avoid repetition).', 'The creation and implementation of a custom repository interface and class, inheriting from the generic repository, is explained, indicating the inheritance of generic operations and additional methods for executing queries and returning a list of objects to the client (quantifiable: explains the inheritance of generic operations and addition of custom methods in the custom repository interface and class).']}, {'end': 1574.108, 'start': 1164.403, 'title': 'Repository and unit of work in application', 'summary': 'Introduces the implementation of repositories and unit of work, explaining methods such as ordering courses, eager loading with paging, and decoupling the application from entity framework, with a focus on testability and efficient data access techniques.', 'duration': 409.705, 'highlights': ['The method uses eager loading to load courses and their authors, then includes ordering, skipping, and taking for paging, with the ability to set default values for page size, making it a flexible technique for efficient data access. eager loading, ordering, skipping, taking, default page size', 'The chapter emphasizes the importance of filtering for pages within the data access code and not in upper layers like services or controllers, advocating the passing of page index and page size parameters as a best practice for efficient data access. importance of filtering in data access code, passing page index and page size parameters', "The use of interfaces and classes such as IUnitOfWork, CourseRepository, and AuthorRepository is explained, with a focus on testability through the ability to mock these interfaces and properties in unit tests, ensuring the application's robustness and reliability. use of interfaces and classes, testability through mocking in unit tests"]}], 'duration': 573.96, 'thumbnail': 'https://coursnap.oss-ap-southeast-1.aliyuncs.com/video-capture/rtXpYpZdOzM/pics/rtXpYpZdOzM1000148.jpg', 'highlights': ['The importance of repositories not returning IQueryable is emphasized, as it can give the wrong impression to upper layers, like services or controllers, that they can use this IQueryable to build queries, which is against the idea of using a repository.', 'The concept of encapsulating queries within repositories to avoid repetition is highlighted, with the getAll method demonstrating the use of toList to return an IEnumerable.', 'The creation and implementation of a custom repository interface and class, inheriting from the generic repository, is explained, indicating the inheritance of generic operations and additional methods for executing queries and returning a list of objects to the client.', 'The method uses eager loading to load courses and their authors, then includes ordering, skipping, and taking for paging, with the ability to set default values for page size, making it a flexible technique for efficient data access.', 'The chapter emphasizes the importance of filtering for pages within the data access code and not in upper layers like services or controllers, advocating the passing of page index and page size parameters as a best practice for efficient data access.', "The use of interfaces and classes such as IUnitOfWork, CourseRepository, and AuthorRepository is explained, with a focus on testability through the ability to mock these interfaces and properties in unit tests, ensuring the application's robustness and reliability."]}], 'highlights': ['The repository pattern decouples applications from persistence frameworks, allowing for easier switching to a different persistence framework with minimal impact on the rest of the application.', 'The repository pattern minimizes duplicate query logic by encapsulating the logic in a repository, reducing code duplication and increasing maintainability.', 'The repository pattern provides the freedom to explore different persistence frameworks with minimal impact on the application.', 'The chapter details the methods within the repository interface, such as get, getAll, find, add, add range, remove, and remove range, providing a comprehensive overview of the available operations for managing objects within the repository.', 'Creating generic repository interfaces and implementing specific interfaces for entities The chapter explains the need for repository interfaces and their generic nature, along with the implementation of specific interfaces for entities like iCourseRepository and iAuthorRepository, allowing for tailored operations for each entity.', 'The chapter discusses the implementation of the repository and unit of work patterns with entity framework, providing a practical approach to working with data access concerns and business logic.', 'The importance of repositories not returning IQueryable is emphasized, as it can give the wrong impression to upper layers, like services or controllers, that they can use this IQueryable to build queries, which is against the idea of using a repository.', 'The concept of encapsulating queries within repositories to avoid repetition is highlighted, with the getAll method demonstrating the use of toList to return an IEnumerable.', 'The creation and implementation of a custom repository interface and class, inheriting from the generic repository, is explained, indicating the inheritance of generic operations and additional methods for executing queries and returning a list of objects to the client.', 'The method uses eager loading to load courses and their authors, then includes ordering, skipping, and taking for paging, with the ability to set default values for page size, making it a flexible technique for efficient data access.']}