Is it wise to use same DbContext with multiple repositories? - c#

Getting deeper with entity framework and repositories in order to enable better testing. Wondering if this is wise though?
public interface IRepository
{
int SaveChanges();
void Dispose();
}
using (MyContext context = new MyContext())
{
TransactionRepository txns = new TransactionRepository(context); // TransactionRepository implement IRepository
MappingRepository maps = new MappingRepository(context); // MappingRepositoryimplement IRepository
SomeCommand command = new SomeCommand(txns, maps);
command.Execute();
}
Each of the repositories is logically different, so in theory could be in different data sources. For now, they use the same database though. Each of the repository classes implements IRepository, and notably SaveChanges() along with some query methods that I've not shown for brevity.
What's a good practice for utilize multiple repositories?

+1 gorilla, some goods points made. I would add the following thoughts.
In web/mvc scenario , I use dozens of repositories and inject the Context into these Repositories. I use a repository base class.
I also UoW classes which use a context in constructor.
The Unit Of Work Classes contains references to all supported repositories for the context. I also use bounded contexts. Here is a sample blogs from Julie Lerman on the subject.
http://www.goodreads.com/author/show/1892325.Julia_Lerman/blog
So yes, it makes perfect sense to use multiple contexts and to use multiple repositories.
You may even have multiple Unit of Work classes, although concurrent use of UoW classes is another discussion.
ADDING SAMPLE code as requested:
This sample is one of Several LuW classes that inherits from a base LuW class.
The current state and DBContext to be use is injected. (or defaulted)
The repositories are interfaces from CORE project. The LuW classes are in the DAL project.
the base LuW is something like....
public interface ILuw : ILuwEvent, IDisposable
{
IBosCurrentState CurrentState{ get; set; }
OperationStatus Commit();
}
The Luw Class itself.
namespace XYZ.DAL
{
public class LuwBosMaster : Luw, ILuwBosMaster
{
public LuwBosMaster(DbContext context, IBosCurrentState currentState)
{
base.Initialise(context,currentState);
}
public LuwBosMaster()
{
base.Initialise(GetDefaultContext(), BosGlobal.BGA.IBosCurrentState);
}
public static DbContextBosMaster GetDefaultContext()
{
return new DbContextBosMaster("BosMaster");
}
//MasterUser with own Repository Class
private IRepositoryMasterUser _repositoryMasterUser;
public IRepositoryMasterUser RepMasterUser
{ get { return _repositoryMasterUser ?? (_repositoryMasterUser = new RepositoryMasterUser(Context, CurrentState)); } }
//20 other repositories declared adn available within this Luw
// Some repositories might address several tables other single tables only.
// The repositories are based on a base class that common generic behavior for each MODEL object
Im sure you get the basic idea...

This really comes down to design decisions on your part. If you're following Unit Of Work pattern, then each repository is probably going to have it's own context; mainly because according to UoW, each repository call should create it's context, do it's work, and then dispose of it's context.
There are other good reasons to share a context though, one of which (IMHO) is that the context has to track the state of an entity, if you're get an entity, dispose the context, make some modifications to the entity, and then attach to a new context this new context has to go hit the database so it can figure out the state of the entity. Likewise if you're working with graphs of entities (Invoices, and all their InvoiceItems), then the new context would have to fetch all the entities in the graph to determine their state.
Now, if you're working with web pages or services where you are not or cannot maintain a state, then the UoW pattern is sort of implied and it's a generally accepted "good practice".

The most important thing is forgotten: The database connection is not shared between multiple DbContext instances. That means that you have to use distributed transactions if you would like several repositories to be in the same transaction. That's a large performance degrade compared to a local transactions.

Related

It is possible to use child class to implement Separation of concerns using EF Core?

My goal is async loading of related entities using DBContext.
Let imagine two projects. The first named MyApp.Domain and contains domain entities.
namespace MyApp.Domain
{
public class PlanPage
{
public Guid Id { get; set; }
}
}
namespace MyApp.Domain
{
public class PlanPageDay
{
public Guid Id { get; set; }
public Guid PlanPageId { get; set; }
}
}
The second project named MyApp.Infrastructure.EntityFramework and contains configuration of projection entities to database. It also contains class which extends domain entity and implements Entity framework specific logic.
namespace MyApp.Infrastructure.EntityFramework.Models
{
public class PlanPageEntity : PlanPage
{
private readonly ApplicationDbContext _applicationDbContext;
protected PlanPageEntity(ApplicationDbContext applicationDbContext)
{
_applicationDbContext = applicationDbContext;
}
public ICollection<PlanPageDay>? Days { get; set; }
public async Task<ICollection<PlanPageDay>> GetDays()
{
return Days ??= await _applicationDbContext.PlanPageDays
.Where(pd => pd.PlanPageId == Id)
.ToListAsync();
}
}
}
The purpose of this example is simple. We separate infrastructure code from domain code. Look how do we plan to use this concept:
// Entity initializing code. Placing somewhere in domain logic.
var plan = new PlanPage(/*some constructor arguments*/);
// Entity loading code. Placing somewhere in infrastructure implementation.
public async Task<PlanPage> GetPlanPage(Guid id)
{
return await _applicationDbContext.Set<PlanPageEntity>().FindAsync(id);
}
Note that we tell to Entity framework to use child class (PlanPageEntity) so it can handle all specific things that it can.
The question is: Is it possible to configure the EF so that it allows us to use this concept?
As requested here's a little more details for my opinion stated in the comments.
The main reason why I think your current approach is a bad idea is that it violates the separation of concerns design principle: when you are mixing domain models with data access models, you make your domain logic completely dependent on how you model the data in your database. This quickly limits your options because the database may have some restrictions on how you can model your data that doesn't fit well with the domain logic you want to implement as well as making maintenance difficult. E.g. if you decide to split up one DB table into two then you might have a big task ahead of you in order to make your domain logic work with those two new models/tables. Additionally, making performance optimizations in your database easily becomes a nightmare if not thought through ahead of time - and you shouldn't spend time thinking of optimizing your system before it's necessary.
I know this is a little abstract since I don't know much about your domain but I'm sure I could find more arguments against it.
Instead, separating data access models (and in general all external data models) from your domain models makes it much easier to maintain: if you need to make some changes to your database, you simply need to update the logic that maps the data from your data access models to your domain model - nothing in your domain logic needs to change.
In the examples you have given, you have already logically separated your domain models and data access models into two separate projects. So why not follow through with that thought and separate the two with a binding/mapping layer in-between?
Is it possible to configure the EF so that it allows us to use this concept?
Yes. Essentially you have DTO's, and your Entities derive from your DTOs. So when you fetch an Entity you can return it directly. But if you wouldn't be able to attach a non-Entity, so you'd have to map it. It's going to be inconvenient, and like 99.999% of bespoke entity and repository designs, will be ultimately a waste of time.
This is somewhat similar to the what EF already does for you. Start with persistence-ignorant Entity classes, and introduce persistence-aware runtime subtypes for scenarios that require them, which is basically just Lazy Loading.

How to design multiple repositories that access the same real-time data using EF?

I am actually looking for some help on learning the ropes on designing multiple Repositories that will access the same database using EF. I have seen sample code where each repository has it's own private DBContext, but am having difficulty with this concept. I am not interested in a Generic Interface in this project.
I want multiple interfaces where one is Identity based (on authorization) and other job specific repositories such as Categories, Items, etc in a single application where the inherited interfaces are reusable, hence the multiple DbContext instances.
In SQL you have transactions where you may commit or rollback the transaction, so in EF would multiple repos access the same (real-time) data? Maybe a better question would be how should I design my DAL when I want a single application to inherit many job specific repositories.
What did jgauffin mean by,
" make sure that your repository is 100% complete abstraction"
What is meant by this?
Here is a quick example of what I am trying to figure out. Is this practice reasonable?
public class OneRepo: IRepository, IDisposable
{
private DbContext context = new DbContext();
// Methods and whatnot...
}
And then a second repository also requires the same db connection by OneRepo but has separate in-memory Unit of Work I think?
public class AnotherRepo: IRepository, IDisposable
{
private DbContext context = new DbContext();
// Methods and whatnot...
}
I apologize if my question is not well-written. I am relatively new to actually posting and I am not sure if I am making myself clear. I have already decided that I am not fond of generic repos in general and would like to create repos based on authorization and/or user tasks using Role Interface pattern. Any help explaining would be greatly appreciated!
You inject the data context into your repositories
public class FirstRepo
{
DbContext _ctx;
public FirstRepo( DbContext ctx )
{
this._ctx = ctx;
}
}
public class AnotherRepo
{
DbContext _ctx;
public AnotherRepo( DbContext ctx )
{
this._ctx = ctx;
}
}
This way you can pass the same context to all repositories under the same unit of work.

Linq to Sql and separation of concerns - am I doing this right?

I have a project that I'm working on that I'm using LINQ to SQL for and I have set up business objects/models to use in my web app. I am looking for some feedback on how I've set all this up to see if it makes sense and if there's anything I should be doing differently.
Here's an example model:
public class User
{
private MyDataContext _db = new MyDataContext();
private MyLINQUserClass _user = new MyLINQUserClass();
public string Name
{
get
{
return _user.Name;
}
set
{
_user.Name = value;
}
}
public User(int UserID)
{
_user = _db.Where(u => u.UserID == UserID).FirstOrDefault();
if (_user == null)
{
_user = new MyLINQUserClass();
}
}
internal User(MyLINQUserClass user, MyDataContext db)
{
_db = db;
_user = user;
}
public void Save()
{
_db.SubmitChanges();
}
public static User Add(string Name)
{
MyDataContext _db = new MyDataContext();
MyLINQUserClass _user = new MyLINQUserClass();
_user.Name = Name;
_db.MyLINQUserTable.InsertOnSubmit(_user);
_db.SubmitChanges();
return new User(_user, _db);
}
public static IList<User> Get()
{
MyDataContext _db = new MyDataContext();
return _db.MyLINQUserTable.Select(u => new User(u, _db)).ToList();
}
}
For clarity, I am using this type of model already quite heavily in the project (the above is just an example I threw together for the post on the fly) and it works very well. My question is more of a "learning" question ... I know it works. I'm just not sure if there is something I should be doing differently that is better and if so, why.
Thoughts?
I suppose there are no right answers to this kind of questions. It is a matter of design, preference and requirements. I will try to show my view...
I always liked the Repository pattern to keep the concerns seperated. I would use a repository of type T to retrieve the T entities (talking generics). These would be the entities participating on my business model. In your case, I would have a UsersRepository class, returning User entities. This Data access layer (DAL) would handle my data access concern.
My business model would use the entities to do its business. In simple CRUD applications, maybe no other objects other the entities returned by my repositories would be needed. In more complicated applications, new classes would be needed, using the repositories of the DAL to retrieve data as entities. This business layer would handle my main business functionality concern (calculations etc).
Then, for display purposes, you could need perhaps another structure. For instance, if you follow the MVC pattern (you could also see the Microsoft article) you would need to create another model to fit your display purposes. This GUI layer following the MVC pattern would handle my graphical display concern.
Hope I helped!
This is the so-called Data Access Objects pattern. The User is a DAO to MyLINQUserClass which might be called the domain class.
The DAO pattern is designed for single responsibility: only the DAO "knows" the data layer while the domain class can concentrate on business logic. The domain class is persistence ignorant. So far, so good.
However, there are (at least) three great drawbacks of this pattern:
It tends to create lots of boilerplate code
It is hard to compose object graphs, because a DAO represents only one row in the database and fetching object graphs easily degenerates into one query per object or collection of child objects.
It is hard to work transactionally, because a DAO can't manage a transaction spanning an entire object graph. So you need some overarching layer to handle transactions.
Most ORMs however, have a different persistence-ignorance model than DAO. They have repositories and units of work. In L2S the Table is a basic repository and the context a unit of work. The "domain" classes, like MyLINQUserClass, can be considered persistence-ignorant. (Admitted, they are stuffed with boilerplate code that serves persistence and change tracking, but it is generated and it can practically be ignored). So all responsibilities for CRUD operations have been assigned, and there's no need for other objects carrying these responsibilities.
The way you implement it makes it extra hard to work with object graphs and transactions because each DAO has its own context, so you can't compose LINQ queries involving multiple DAO's in a way that the LINQ is translated into one SQL statement. And doing multiple save operations in one transaction is a challenge.
Conclusion
By using DAO in a linq-to-sql environment you're mixing CRUD responsibilities. You get all the disadvantages of the DAO pattern and can't exploit the power of the repository/UoW pattern to the full. I would strongly recommend to make a choice for one or the other, and I would choose L2S (well, actually I would choose Entity Framework).

Interface (interface in interface) in the Entity Framework

I've got two entities in the entity framework. Now I want to seperate them by putting an Interface of the DAL entity into the Domain.
So the end result would be:
DAL
Person : IPerson (EF Entity)
Book : IBook (EF Entity)
Domain
Interfaces (Folder)
IPerson
IBook
Person (Domain entity)
Book (Domain entity)
Now the problem is, should my Dal.Person have a virtual Book or IBook?
How should both the DAL.Person, IPerson and Domain.Person look like (give me just really small example for the interfacing)
EF doesn't support working with interfaces so you cannot have public virtual IBook ... in your Person entity if you want to use it as navigation property handled by EF.
The answer to your question entirely depends on your objective here.
If you are creating domain level Interfaces with the rationale that you might (at some stage later) swap over the DAL from Entity Framework to something entirely different (such as a 3rd party web-service, or perhaps xml serialisation) - then you will be aiming to completely seperate any concrete logic between the Domain and the DAL.
Where possible, you want your Domain to operate on the Domain entites/interfaces and your DAL to operate on DAL entities/interfaces, whilst implementing the interfaces specified in your Data Access
Therefore, your DAL object DAL.Person should contain a Book object, and implement from the IPerson interface at a domain level.
I'll give some examples as requested:
#region Domain Objects
public interface IPerson
{
List<IBook> Books { get; private set; }
}
public interface IBook
{
string Name { get; private set; }
}
#endregion
#region DAL/Entity Framework Auto Generated classes
public class Person : IPerson
{
public List<Book> Books {get; private set;}
}
public class Book : IBook
{
public string Name { get; private set; }
}
#endregion
Contrary to Jodrells comment, I think that if there was a requirement to 'Hot-Swap' the Data Access Layer there could be a case for the DataAccess layer implementing the interface contracts described in the Domain layer.
To be honest though, it is rare that I have seen this requirement - and usually you are best off extending the auto-generated Entity Framework classes (through partial) and passing around the application, removing the duplication that would be required by specifying the domain objects and contracts themselves.
So in essence, your Entity-Framework classes becomes your Domain layer.
And I should mention that you should use POCO classes as per comments above
I've not seen Interfaces used to decouple EF. I know they are used for decoupling with dependency injection, but perhaps there is too much going on with EF behind the scenes for this to work (dynamic proxies, change detection).
I'd suggest implementing a Repository layer.
Step 1
Start with the simplest pattern - model (Person and Book) in a domain and EF in a DAL layer, using the standard EF procedure for code first. EF implements repository features in the DbSet<Person> and DbSet<Book> (but of course this type of repository is locked into EF).
Make a deliverable app work with this pattern, you can demo functionality quite quickly. This allows you to focus on app logic and not worry too much about persistence.
Step 2
Put a repository class or classes between domain and DAL. Replace the domain calls to DbSet<Person> and DbSet<Book> with calls to IQueryable<Person> and IQueryable<Book> in the repository. The repository collections initially just point at the EF DbSet<> collections.
Implement Save() in the repository as well. Initially, it just calls DbContext.SaveChanges().
Check the functionality stays the same.
Step 3
Replace the source of the repository IQueryable<>'s with whatever is equivalent in your new DAL. This may or may not be tricky, depending on the shape of the new DAL.
I followed this kind of process - started with an XML serialized DAL, moved it to EF, refactored one table back to a local XML file, and next step will be to refactor another table to a web service on an ESB.
BTW, you mention replacing EF with SQL for performance. We found EF slow for bulk inserts, because of the row-by-row style it uses.
To get around this, I implemented SqlBulkCopy within the EF based repository (instead of wholesale replacement of EF which has other features we really liked). It's quick, but takes a while to piece together.
I've been having this problem for AGES.
In the past I have used DTOs with AutoMapper, but this never seemed very elegant, but I think I've found a slightly neater way - have a look and see if it suites your design.
Basically you expose TWO links in your - in your concrete class - one implemetents the Ibook Book and one that implements Book BookNavigation
the first one implements the interface requirements (Ibook) and the second implements a concrete class to make EF Happy. You then bind the two to the SAME underlying private Book book.
I explain it in more detail here:
http://bretthargreaves.wordpress.com/2014/11/11/entity-framework-and-interface-issues/

EF4.0, repositories, and Ninject 2

This is in continuation of two ongoing problems I'm facing: Problems trying to attach a new EF4 entity to ObjectContext while its entity collection entities are already attached and EF4.0 - Is there a way to see what entities are attached to what ObjectContext during debugging? I'm using this space to ask another somewhat complicated question, and I don't want to make a huge, ultra long question out of my other threads.
So, a quick rundown:
I have incoming form data which is bound to a DTO. I want to map the DTO to an Entity (a Game entity). The wrinkle is that the Game contains a EntityCollection which I must create and Add() to the Game based on a int[] in the DTO (each integer represents the ID of a Platform). And, naturally, EF4 is choking in part because it's a many-to-many relationship, but also, I think, because there's some shenanigans going on with how many ObjectContext objects are in play. I keep getting an exception claiming I can't add my retrieved Platform entities to my new Game entity because they belong to two different ObjectContexts. I can't see how that is possible given my current set up, but I'm not sure what else the problem could be.
Okay, so I have three repositories which I inject into my controller via Ninject interface injection. I create the ObjectContexts in each like so:
public class HGGameRepository : IGameRepository
{
private HGEntities _siteDB = new HGEntities();
// rest of repo
}
The other two repositories are built the same way.
My Ninject DI code is fairly simple:
private class HandiGamerServices : NinjectModule
{
public override void Load()
{
Bind<IArticleRepository>().To<HGArticleRepository>().InRequestScope();
Bind<IGameRepository>().To<HGGameRepository>().InRequestScope();
Bind<INewsRepository>().To<HGNewsRepository>().InRequestScope();
Bind<ErrorController>().ToSelf().InRequestScope();
}
}
From what I've read, this should create these bindings once per HTTP request.
What I'd like to do is have one instance of my HGEntities object be shared among all repositories in order to ensure I have one and only one ObjectContext in play. I'm just unsure how to do it.
Is there a standard way to do this?
Here's one option:
Change your repositories to take in an interface, IHGEntities, in their constructor and hook up HGEntities into your NinjectModule the same you did with your repositories. That way, when your controllers need an instance of IArticleRepository, Ninject will either instantiate an instance of HGEntities to pass into the repositories or use the instance that is already active in the current HTTP context.
Then, inside your repository classes you can simply cast IHGEntities to HGEntities.

Categories

Resources