When multiple users are editing the same data, concurrency effects can result in lost work or errors. This course teaches you how to prevent concurrency errors at database level, and for business transactions that span multiple pages and postbacks.
When developing applications where multiple users can edit the same data, concurrency effects can result in work being overwritten and inconsistent data being read, which can cost a business time, money, and frustration. In this course, Enterprise Patterns: Concurrency in Business Applications, you'll learn how to recognize and prevent these types of errors. First, you'll explore how to use isolation levels within database transactions. Next, you'll discover how to implement optimistic and pessimistic concurrency in code for long-running business transactions. Finally, you'll learn how to design a locking framework for your application. When you’re finished with this course, you'll have a foundational knowledge of concurrency patterns that will help you as you move forward to design more robust, enterprise applications. Software required: Microsoft Visual Studio.
Neil is a solutions architect and developer, with a passion for web development, architecture, and security. He has worked in large and small IT organizations, written articles on development, and spoken at local .NET user groups. Neil has several Microsoft Certifications, including MCPD, MCSA, and MCSD.
Course Overview Hi everybody. My name is Neil Morrissey, and welcome to my course, Enterprise Patterns: Concurrency in Business Applications. When more than one user tries to update the same piece of data at the same time, a whole host of concurrency errors can occur like lost updates, dirty reads, and phantom reads. Not only can users lose work, but strange errors can appear in everything from the user interface, to calculations, to even reports if you don't take concurrency into account when designing your application. In this course, we'll examine how to prevent concurrency issues at two levels. At the database level, we'll look at how isolation levels work in system transactions, and then at a higher level, we'll examine concurrency in business transactions, where a user performs operations that span multiple pages and post backs before committing their data. If someone else modifies the data during that time, work can get overwritten and lost. We'll be examining concurrency control for business transactions using design patterns from Martin Fowler's famous book, Patterns of Enterprise Application Architecture. The examples in this course are in the latest versions of ASP. NET Core and Entity Framework Core, but these are design patterns, you're going to learn the concepts really well, so regardless of what language and platform you code in, you'll gain an understanding of how to implement these patterns. Some of the major topics we'll cover include understanding and recognizing types of concurrency errors, how to handle concurrency at the database level using transactions and isolation levels, as well as features of Entity Framework Core, how to implement optimistic and pessimistic concurrency control, how to handle concurrency for groups of objects like a customer and their addresses, and how to build concurrency control into a framework in your application, so you can ensure that you and other developers on your team don't bypass your concurrency strategy. This is a topic that's often overlooked in system design, so knowing these patterns will add to your toolbox and make you a better application designer and developer. While you don't need any prior experience to follow the concepts and patterns in this course, if you want to get the most out of the demos, you'll need a basic understanding of ASP. NET and the Entity Framework. I'm really excited to show you how you can use these patterns to make your applications more robust, so I hope you'll join me on this journey to learn Enterprise Patterns: Concurrency and Business applications here on Pluralsight.
Implementing the Optimistic Offline Lock Pattern When two users are modifying the same record, each in their own business transaction, data integrity is at risk. Most commonly, this can take the form of lost updates and inconsistent reads. This module is about the Optimistic Offline Lock pattern, one of the patterns in Martin Fowler's book, Patterns of Enterprise Application Architecture. This pattern addresses concurrency conflicts by detecting the conflict just before changes are saved, and rolling back the change if another business transaction has modified the record. The assumption here is that the chance of conflict is relatively low. When the chance of conflict is high, you'll want to look at the Pessimistic Offline Lock pattern, which prevents anyone else from being able to modify the record while it's being edited. So in this module, we'll start with an overview of the pattern, then we'll look at the built-in support for optimistic concurrency in Entity Framework Core and SQL Server. Next you'll see an overview of the demo application we'll be refactoring throughout the rest of the course and using to implement these patterns. Then we'll implement Optimistic Offline Lock for one of the entity types in the application. Then I'll show you how you can manage the state of disconnected entities to control which ones get updated in the database when they're added back to the DB context. And finally, we'll look at implementing the pattern for deletes. So let's get started with an overview of the Optimistic Offline Lock pattern.
Implementing the Pessimistic Offline Lock Pattern The Pessimistic Offline Lock pattern prevents conflicts by avoiding them all together. This pattern is used when you have a business transaction that needs to notify the user up front that another user is editing or even reading the record, depending on how you choose to implement it. In this module, we'll start with an overview of the pattern, then we'll build the lock manager in code, and show how it can be used when editing entities. Next, you'll see how to deal with locks for expired or abandoned sessions. And finally, we'll go through an example of using the pattern with deletes. So let's get started with understanding the concepts needed to implement the pattern.
Implementing the Coarse-grained Lock Pattern So far we've seen how you can lock individual records using the Optimistic and Pessimistic Offline Lock patterns, but often you'll want to edit items in a group, and it makes sense to lock all the items at once, rather than maintain locks for each individual item. In this module, we'll do just that with the Coarse-Grained Lock pattern. We'll start by examining the pattern. Then we'll expand on the demo project by implementing a business transaction that spans multiple pages and post backs. Next, you'll see how to track the state of offline entities before they're saved back to the database as a group, and we'll end by implementing the Coarse-Grained Lock pattern using optimistic concurrency. So let's get started by understanding the Coarse-Grained Lock pattern.
Implementing the Implicit Lock Pattern When you're implementing the locking patterns we've examined in the previous modules, the most important thing is consistency. If you or someone on your team forgets to take a lock on an object, the whole locking scheme becomes useless. Failing to get a pessimistic lock up front means you could overwrite someone's data, the same with failing to get the version information up front for an optimistic lock. Forgetting to release locks could leave the database full of abandoned locks, which could reduce concurrency of the system until those locks expire, and these type of issues are difficult to test, especially with automated tests. The Implicit Lock pattern is a way of building your locking strategy into a framework in code, so it's difficult to make errors in locking objects. This is the fourth pattern in the course from Martin Fowler's book, Patterns of Enterprise Application Architecture. In this module, we'll start by examining the pattern. Then we'll implement it for the Coarse-Grained Optimistic Offline Lock that we created in the previous module. We'll start by refactoring our ChangeRepository class into a generic base class that can be inherited from by any repository type. In that class, we'll refactor the get method to include all the navigation properties of the entity, including the version information used by our locking strategy. That way, we know the version is always loaded up front, and then we'll refactor the save method to make sure there's a version object included in the save, so we get the optimistic concurrency checking that we expect. So let's get started by understanding the Implicit Lock pattern.