SlideShare una empresa de Scribd logo
1 de 13
Multi-Tenancy: Beyond the Whiteboard Chris Hefley, Bandit Software Blog: http://indomitablehef.com Email: indomitablehef@gmail.com Twitter: @indomitablehef
Multi-Tenancy
The Big Decision Database Per Tenant Schema Per Tenant Tenant Id per Row Tenant as Aggregate Root
Other Considerations The Url  app.com  		(salesforce.com) tenant.app.com  	(me.basecamphq.com) app.com/tenant 	(facebook.com/me) tenant.com  		(mynewyahoostore.com) Data access ORM Dynamic SQL Stored Procedures
Design Goals Agnostic Secure Maintainable
Design Patterns: Repository Domain Model public class Person {…} Repository (PersonRepository) repository.Find(PersonQuery q) {…return Person} repository.Remove(Person p) {} respostory.Add(new Person {…}) repository.ListByProject(Project p) {…return List<Person>} Data Access Layer dao.RetrieveOne(Dictionary<string,object> parameters) dao.Delete(person.Id)  dao.SaveOrUpdate(Person p) dao.RetrieveAll( Dictionary<string,object> parameters)
Repository as Boundary Your Application “Knows Nothing” Repository Effectively adds: “WHERE TenantId =“ To every set of criteria passed on to the data layer
Design Patterns: DI/IOC
Inversion of Control
Inversion of Control
First Benefit: Testing
But wait, there’s more!
SokMunkae Data Model Organization User Project Task

Más contenido relacionado

Similar a Dev Link2009 Multi Tenancy Beyond The Whiteboard Chris Hefley

Building Social Enterprise with Ruby and Salesforce
Building Social Enterprise with Ruby and SalesforceBuilding Social Enterprise with Ruby and Salesforce
Building Social Enterprise with Ruby and SalesforceRaymond Gao
 
Elegant Rest Design Webinar
Elegant Rest Design WebinarElegant Rest Design Webinar
Elegant Rest Design WebinarStormpath
 
Advanced Web Development
Advanced Web DevelopmentAdvanced Web Development
Advanced Web DevelopmentRobert J. Stein
 
Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!Oliver Gierke
 
External to DA, the OS X Way
External to DA, the OS X WayExternal to DA, the OS X Way
External to DA, the OS X WayStephan Borosh
 
Graphql + Symfony | Александр Демченко | CODEiD
Graphql + Symfony | Александр Демченко | CODEiDGraphql + Symfony | Александр Демченко | CODEiD
Graphql + Symfony | Александр Демченко | CODEiDCODEiD PHP Community
 
Basic of Big Data
Basic of Big Data Basic of Big Data
Basic of Big Data Amar kumar
 
Big data, just an introduction to Hadoop and Scripting Languages
Big data, just an introduction to Hadoop and Scripting LanguagesBig data, just an introduction to Hadoop and Scripting Languages
Big data, just an introduction to Hadoop and Scripting LanguagesCorley S.r.l.
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceMaarten Balliauw
 
12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocratlinoj
 
Introduction to data science with H2O-Chicago
Introduction to data science with H2O-ChicagoIntroduction to data science with H2O-Chicago
Introduction to data science with H2O-ChicagoSri Ambati
 
Introduction to Data Science with H2O- Mountain View
Introduction to Data Science with H2O- Mountain ViewIntroduction to Data Science with H2O- Mountain View
Introduction to Data Science with H2O- Mountain ViewSri Ambati
 
Django tech-talk
Django tech-talkDjango tech-talk
Django tech-talkdtdannen
 
Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01Tony Frame
 

Similar a Dev Link2009 Multi Tenancy Beyond The Whiteboard Chris Hefley (20)

Services Stanford 2012
Services Stanford 2012Services Stanford 2012
Services Stanford 2012
 
Building Social Enterprise with Ruby and Salesforce
Building Social Enterprise with Ruby and SalesforceBuilding Social Enterprise with Ruby and Salesforce
Building Social Enterprise with Ruby and Salesforce
 
Elegant Rest Design Webinar
Elegant Rest Design WebinarElegant Rest Design Webinar
Elegant Rest Design Webinar
 
Advanced Web Development
Advanced Web DevelopmentAdvanced Web Development
Advanced Web Development
 
Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!Data access 2.0? Please welcome: Spring Data!
Data access 2.0? Please welcome: Spring Data!
 
HackMiami-Final
HackMiami-FinalHackMiami-Final
HackMiami-Final
 
External to DA, the OS X Way
External to DA, the OS X WayExternal to DA, the OS X Way
External to DA, the OS X Way
 
Symfony + GraphQL
Symfony + GraphQLSymfony + GraphQL
Symfony + GraphQL
 
Graphql + Symfony | Александр Демченко | CODEiD
Graphql + Symfony | Александр Демченко | CODEiDGraphql + Symfony | Александр Демченко | CODEiD
Graphql + Symfony | Александр Демченко | CODEiD
 
Tornadoweb
TornadowebTornadoweb
Tornadoweb
 
Basic of Big Data
Basic of Big Data Basic of Big Data
Basic of Big Data
 
Big data, just an introduction to Hadoop and Scripting Languages
Big data, just an introduction to Hadoop and Scripting LanguagesBig data, just an introduction to Hadoop and Scripting Languages
Big data, just an introduction to Hadoop and Scripting Languages
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to Space
 
12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat12 core technologies you should learn, love, and hate to be a 'real' technocrat
12 core technologies you should learn, love, and hate to be a 'real' technocrat
 
Introduction to data science with H2O-Chicago
Introduction to data science with H2O-ChicagoIntroduction to data science with H2O-Chicago
Introduction to data science with H2O-Chicago
 
Introduction to Data Science with H2O- Mountain View
Introduction to Data Science with H2O- Mountain ViewIntroduction to Data Science with H2O- Mountain View
Introduction to Data Science with H2O- Mountain View
 
Django tech-talk
Django tech-talkDjango tech-talk
Django tech-talk
 
Java at lifeblob
Java at lifeblobJava at lifeblob
Java at lifeblob
 
New PHP Exploitation Techniques
New PHP Exploitation TechniquesNew PHP Exploitation Techniques
New PHP Exploitation Techniques
 
Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01Googleappengineintro 110410190620-phpapp01
Googleappengineintro 110410190620-phpapp01
 

Último

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilV3cube
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessPixlogix Infotech
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century educationjfdjdjcjdnsjd
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 

Último (20)

Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Developing An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of BrazilDeveloping An App To Navigate The Roads of Brazil
Developing An App To Navigate The Roads of Brazil
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 

Dev Link2009 Multi Tenancy Beyond The Whiteboard Chris Hefley

Notas del editor

  1. Ok, let’s get started. Hi, everyone, I’m Chris Hefley. The title of this talk is Multi-Tenancy, Beyond the whiteboard. First off, I’ll say that this is the kind of talk where a lot can go wrong. I’m going to try to show you some running code, stepping through it in the debugger and all, so if you see me do something stupid, speak up…d m on’t let me flounder. Feel free to ask questions at any time, but if you have one and want to hold till just the right moment, watch for those times when Visual Studio starts grinding away on something, when there would normally be an awkward silence, and go ahead and just holler out your question then. I’ll admit now that some of the examples I promised you, like Linq2Sql, are not in here. I can’t get the visual designer for Linq2Sql or the server explorer to show up in Visual Studio on this machine right now, so I didn’t get a chance to do that one. But the important stuff here is architectural, and whether you use Lin2Sql or NHibernate or just roll your own isn’t so important. And hopefully I can leave time for some lively discussion at the end.
  2. First off, what is Multi-Tenancy? In simplistic terms, it the architecture we use to offer software as a service, where a single instance of your application is used by multiple clients, each of whom has their own, usually private, virtual copy of the application just for them. When you sign up for a BaseCamp or SalesForce.com or Facebook account, you are becoming a tenant in someone’s multi-tenant application.
  3. The biggest architectural decision you are going to have to make when developing a multi-tenant application is how to partition the data for different tenants. We’re just going to skim over these and acknowledge that each has it’s place, without debating all the pros and cons and dealing with all the religious wars that ensue. The code and design patterns we are going to look at later, however, will help you to implement some of these data partitioning schemes, so we’ll just describe each briefly here and move on.Ok, so first off, there’s Database Per Tenant In some verticals, like Healthcare and Financials, this may be the only option you have for some applications. It’s great for security, but can get very difficult to maintain if you’re not very strict and very careful to keep everything in sync.In Schema per tenant, there’s one database, but a separate copy of each table for each tenant. In TenantID per Row, every row in every table has a TenantID column. Every database query from you application includes “Where TenantID = The CurrentTenantId”. One of the nice things about this approach is that it’s easy to change your mind and switch to a separate database, if you want to. It’s easy to extract the data for one client from the system, by just copying everything from all tables that has the same TentantIDIn Tenant as Aggregate Root, the “Tenant” or “Organization” or “Client” table is the parent of every other table in the model. So for a project management application, you might have an Organization, which has a one-to-many relationship to the Projects table and the Users table. The Projects table would have a one-to-many relationship to the ProjectItems table and the Milestones table, etc. Your application has to enforce the separation by always joining to the appropriate parent table when retrieving things from the database.
  4. Some other considerations that will come up:The Url. Does everyone log into the app at the same url? My personal favorite is the subdomain approach, which can even be expanded so that you have tenant.subtenant.app.comThis third choice is especially nice for social applications like twitter and facebook, where each tenant is actually part of a larger community, and shares information with other tenants and possibly the public.And finally, for some applications it makes sense to allow the client to supply their own domain name, which you redirect to their hosted instance of your app. In some cases like when opening a Yahoo! Store, buying a domain name and having it set up for you can even be part of the signup process for your mult-tenant application.As far as data access strategy, you have object-relational mappers like Nhibernate, EntityFramework, Linq2Sql, or you can write your own dynamic sql queries in your app, or use stored procedures.
  5. The first design pattern we’re going to look at is the Repository pattern. Basically, a repository is an object that sits between your domain model and you data access layer. It provides an object oriented abstraction over data access. While the methods on your data access objects are going to be the pretty typical “CRUD” methods, the methods on your repository will be more meaningful in terms of your application domain.You might have a Find method that takes a “Query” object – basically an object that looks something like the object you are searching for, in this case Person, and has the fields filled in that you are interested in. So, personQuery might have all it’s fields = null, but the username field has “chris” and maybe there’s an enum that allows to specify “begins with”, “contains” or “exact”.The repostory could deconstruct that patientQuery, call the Data Access method (RetrieveOne or RetrieveAll), and pass in a list of relevant parameters that get turned into a real database query.You might also have meaningful methods like ListUsersByProject that eventually get turned into the more mundane parameters and database query by the data access layer.Take a look at the code:IRepostory<T>IUserRepositoryUserRepository
  6. I proposed earlier that for most multi-tenant applications, the bulk of the application should be blissfully ignorant of the fact that it is a multi-tenant application. (again, the exception is a community application like Facebook, where interacting with the other tenant is desirable).I’m proposing now that the Repository should be that boundary in your application where, everything above the respository “Knows nothing” of Multi-Tenancy. This includes those application services that instantiate and call the methods on the repository – they should not be passing a TenantId into repository methods, they should just ask for the objects they want, and the repository should figure out that they mean….all the objects they want “for the current tenant”.So, if the application can’t tell the repository which Tenant it belongs to, then how does the repository get that information?
  7. The answer lies in our next pattern: Dependency Injection and Inversion of Control. When I look back over my career, I can identify moments in my growth process where I learned some new concept, or finally really, really understood some concept that had been vague before, but suddenly became clear. I can identify certain ones of those moments that were “game changing” – after which what I learned began to effect everything I did – and became part of almost every bit of code I wrote.This is one of those. Until you really grasp it, it looks a little intimidating to most people. At least, it did to me at first. But once I stopped just reading blog posts about how important some people thought it was, and rolled up my sleeves and decided to try it, I found that it is really, really simple. I mean, really simple.Now I’m not sure I can teach this design pattern effectively with four slides. But I’m going to dispense with all the formal definitions, and I’m not going to try to show you a complete understanding of how it works, but I’m going to show a very simple example of the most common way in which I use it, that hopefully will be an ah-hah moment for some of you.Here you have UserRepository class, and it depends on a DataAccess object to actually create queries and retrieve records from the database.In the first example, you have this dependency, so you just ensure that you “new up” an instance of the object you need.The second bit of code is an example of something called “contstructor injection” – that is, you “inject” the depended upon objects into your class via the constructor. No big deal, right? So, let’s think about the implications of doing it this way. Obviously, whoever creates the UserRepository will have to create an instance of the User DAO and pass it into the constructor for UserRepository when it gets created. So wait a minute, is that better than what we had before? Haven’t we increased our dependencies, not decreased them? Now, my UserAdminService class that uses the UserRepository to perform its work will have to know about the DAO? Well, that sucks.
  8. But wait, there’s more. What we just saw was dependency injection. Another pattern, which can be seen really as the second half of the same pattern, is called Inversion of Control. Now there are a lot of freely available Inversion Of Control implementations out there, and all of them have more features than this, but in order to make it simple, I’ve contrived the most basic example of an IOC Container (that’s inversion of control container) that you may ever see.
  9. I thought I was really cooking when I started using Dependency Injection, because it made it so much easier to isolate the components I wanted to test, by allowing me to provide mock objects for the dependencies I wasn’t trying to test.But at that point, the whole IOC container thing was just sort of “there” for me…I was basically breaking my application up into smaller pieces and removing the connections between them, and it was the IOC containers job to piece those all together for me when I was actually running my application, and not just running tests.But the real power of an IOC container is what we’re going to use it for today. I said before that we wanted our repositories to be the boundary in our application, so that the repository would know about the Tenant, but the rest of the application would not. We’re going to do that by “injecting” knowledge of the tenant into the repository, and depending on our IOC container to supply that knowledge to the repository when it is instantiated.