I've been googling a ton on repository patterns with Linq over the last few days. There's a lot of info out there but it's often contradictory and I'm still looking for a definitive source.
One of the things I'm still not sure about is whether the repository should instantiate it's own DataContext and have a SubmitChanges method, or if the DataContext should be injected and the submission handled externally. I've seen both designs but no real comment on the reasoning.
Anyway, the following pattern is pretty common
class Repository<T>
{
DataContext db = new LinqDataContext();
public IEnumerable<T> GetAll() { ... }
public T GetById() { ... }
... etc
public void SubmitChanges() { ... }
}
So my main question is, with the above implementation, why does the repository not need to implement IDisposable? I've seen literally hundreds of examples as above, and none of them seem to bother disposing the DataContext. Isn't this a memory leak?
Disposing a DataContext closes the underlying connection if you have autoclose set to false. If you do not call dispose, you have to wait for the GC to call it for you. You should implement IDisposable and dispose of your repositories which should in turn dispose their DataContext.
Another solution is to create a new data context for each method in your repository if your methods don't work together within a single transaction. Then you can dispose your contexts as soon as they are used via a using() directive.
Not necessary but you probably should implement IDisposable.
Related
I'm a little bit familiar with Entity Framework for some simple projects, but now I want to go deeper and write better code.
There is plenty of topics talking about whether using statics methods in DAL or not. For the moment I'm more of the side of people who think yes we can use statics methods.
But I'm still thinking if some practices are good or not.
Lot of people do like this:
public IList<Person> GetAll()
{
using (var dbContext = new MyDbContext())
{
return dbContext.Persons.ToList();
}
}
But I'm wondering if doing like this is a good practice:
public static IQueryable<Person> GetAll()
{
var dbContext = new MyDbContext();
return dbContext.Persons;
}
The goal is to use only static methods in a static class as I think it's legit because this class is just a DAL, there will never be any property. I also need to do like this instead of using the using() scope to avoid disposing the context as this method return an IQueryable.
I'm sure some people already think "OMG no, your context will never be disposed", so please read this article: http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext.html
I tried by myself and yes the context is disposed only when I don't need it anymore.
I repeat, the goal here is to use static methods so I can't use a dbContext property which the constructor instantiate.
So why people always use the using() scope?
Is it a bad practice to do it like I would like to?
Another bonus question: where is the [NotMapped] attribute with EF6? I've checked on both System.ComponentModel.DataAnnotations and System.ComponentModel.DataAnnotations.Schema but can't find it, this attribute is not recognized by the compiler.
Thank's for your answers
Following the Repository pattern, IQueryable<T> shall never be returned anyway.
Repository pattern, done right
Besides, your repositories depend on your DbContext. Let's say you have to work on customers in an accounting system.
Customer
public class Customer {
public int Id { get; protected set; }
public string GivenName { get; set; }
public string Surname { get; set; }
public string Address { get; set; }
}
CustomerRepository
public class CustomerRepository {
public CustomerRepository(DbContext context) {
if (context == null) throw new ArgumentNullException("context");
this.context = context;
}
public IList<Customer> GetAll() { return context.Customers.ToList(); }
public IList<Invoice> GetInvoicesFor(Customer customer) {
return context.Invoices
.Where(invoice => invoice.Customer.Id == customer.Id)
.ToList();
}
private readonly DbContext context;
}
So in fact, to answer your question in a more concise and precise way, I think neither approach is good. I would more preferably use a DbContext per business concern. When you access let's say the Customers Management features, then instantiate a single DbContext that shall be shared across all of your required repositories, then dispose this very DbContext once you exit this set of features. This way, you shall not have to use Using statements, and your contexts should be managed adequately.
Here's another short and simple good reference for the Repository pattern:
Repository (Martin Fowler)
In response to comments from the OP
But actually the point is I don't want to follow the repository pattern. People say "what about if your data source change?" I want to answer, what about if it never change? What the point of having a such powerful class but not using it just in case one day the database provider may change
Actually, the Repository Pattern doesn't only serve the purpose of easier data source change, it also encourages better separation of concerns and a more functional approach closer to the business domain as members in the repository shall all revolve around business terminologies.
For sure the repository itself cannot take over control to dispose a data context or whatever the object it uses to access the underlying data source, since it doesn't belong to it, it is only lended to it so that it can fulfill its tasks.
As for your point about will the data source change someday? No one can predict it. It is most likely to never change in most of the systems I have worked on. A database change is more likely to be seen after 10 years of the initial development for moerdnization purposes. That day, however, you'll understand how the Repository Pattern saves you time and headaches in comparison to a tightly coupled code. I work with tightly coupled code from legacy systems, and I do take the advantages for benefits. Prevention is better than cure.
But please lets focus on instantiate the dbContext in methods without the using() statement. Is it really bad? I mean also when we inject the context in the constructor we don't handle the dispose(), we let entity framework doing it and it manages it pretty well.
No, it isn't necessarily bad not to use using statements, as long as you dispose all unnecessary resources as long as they are no longer used. The using statements serves this purpose for you by doing it automatically instead of you having to take care about.
As for the Repository pattern, it can't dispose the context that is passed to it, and it shan't be disposed neither because the context is actually contextualized to a certain matter and is used across other features within a given business context.
Let's say you have Customer management features. Within them, you might also require to have the invoices for this customer, along with the transaction history. A single data context shall be used across all of the data access as long as the user works within the customer management business context. You shall then have one DbContext injected in your Customer management feature. This very same DbContext shall be shared across all of the repositories used to access your data source.
Once the user exits the Customer management functionalities, the DbContext shall get disposed accordingly as it may cause memory leaks. It is false to believe that as long as it is no longer used, everything gets garbage collected. You never know how the .NET Framework manages its resources and how long it shall take to dispose your DbContext. You only know that it might get disposed somehow, someday.
If the DbContext gets disposed immediately after a data access is performed, you'll have to instantiate a new instance everytime you need to access the underlying data source. It's a matter of common sense. You have to define the context under which the DbContext shall be used, and make it shared across the identified resources, and dispose it as soon as it is no longer needed. Otherwise, it could cause memory leaks and other such problems.
In response to comment by Mick
I would go further and suggest you should always return IQueryable to enable you to reuse that result passing it into other calls on your repositories. Sorry but your argument makes absolutely no sense to me. Repositories are not meant to be stand-alone one stop shops they should be used to break up logic into small, understandable, encapsulated, easily maintained chunks.
I shall disagree to always return IQueryable<T> through a Repository, otherwise what is it good to have multiple methods for? To retrieve the data within your repository, one could simply do:
public class Repository<T> where T : class {
public Repository(DbContext dataContext) { context = dataContext; }
public IQueryable<T> GetAll() { return context.Set<T>(); }
private readonly DbContext context;
}
and place predicates everywhere in your code to filter the data as per the views needs or whatsoever. When it is time to change the filter criterion or the like, you'll have to browse all of your code to make sure anyone didn't use a filter which was actually unexpected, and may cause the system to misbehave.
On a side note, I do understand your point and I might admit that for some reasons as described in your comment, it might be useful to return IQueryable<T>. Besides, I simply wonder for what good is it, since a repository's responsibility is to provide a class everything it needs to get its information data. So if one needs to pass along IQueryable<T>s to another repository, it sounds strange to me as if one wouldn't have completely investigated every possible way to retrieve data. If one need some data to process another query, lazy-loading can do it and no need to return IQueryables. As per its name, IQueryables are made to perform queries, and the Repository's responsibility to to access the data, that is, to perform queries.
I have some confusion in Linq to SQL.I am searching for an actual reason why Data context class gives follwing Exception some times .
"There is already an open data reader associated with this command which must be closed first
Specially in multitasking environment.Most people are saying that the reason is ,Data Context is not thread Safe.All are suggesting to use DataContex as one per unit of work.
Please refer following thread for best answer
Linq-to-SQL Data Context across multiple threads
But in my case,i am using another class call "A" which is implemented in Singleton pattern.Purpose of this class is ,provide Data context object in singleton manner.I am maintaining instance of this class "A" as global instance in derived class and calling to Datacontex by using particular instance.
My question is,
Will my method call cause uncontrolled memory growth ? based on my understanding,singleton maintaining one instance as static object .If my assumption is wrong ,please give me good explanation.
Note:
Any way my method call also throws same exception.So i am sure same problem is happen in this scenario also.
Your approach will cause problems in general. A DataContext is not intended to be a singleton. Just don't do it.
Even if A is a singleton, create a new DataContext within the appropriate methods within A, rather than having a DataContext as a variable within A. (You might also want to consider whether A should really be a singleton in the first place.)
I actually came here because I felt a singleton pattern would be perfect for the Linq Datacontext too. But after seeing your issues it makes since why it's not.
Here's an example of how I'd write a Singleton Linq DataContext:
class DataAccess
{
private static DataContext db = null;
private DataAccess()
{
}
public static DataContext GetInstance()
{
return db ?? (db = new DataContext());
}
}
In the singleton pattern you set the DataContext instance as static. Well, in a multi-threaded environment a static object is going to cause collisions like the errors you're seeing. You are lucky to get those errors. Using multiple threads you could submit changes from another thread and then have the original thread submit causing a big mess.
I'd stick to non static implementation. True me I know it's disappointing, I really wanted to use that pattern here too.
I implemented a repository pattern to my application dat .
I have :
public class EFRepository<T>
{
DbContext // My db context
public IQureable<T> GetQuery()
{
DataContext.CreateQuery(...);
}
}
Now let say I have user repository :
public class UserRepository : EFRepository
{
public UserGetUserDetails(int userId)
{
GetQuery().Where(u=>u.Id = userId).First();
}
}
my problem is how to release the DbContext when I use the EF repository in derived repositories.
Lets say : UserRepository: EFRepository , and it uses the GetQuery then I have to dispose the context.
Any good idea how to make this in generic repository?
You should think about what unit of work you have. (there are many other tutorials on the internet). The idea is to keep the same dbcontext and to re-use it while being in the same unit of work. This way, entities will already be attached to the context when needing them, etc..
Now, this being a web application, your unit of work would be in this case a request. While in the same request, reuse your DBContext. There are many ways to do this and just off the top of my head - you will want something like 'OnActionExecuting' where you take care of your context.
But even better would be to use an Inversion of Control pattern (there are many frameworks out there that use this, i primarily use NInject . This will automatically create a new instance of a certain class, when needed, depending on the scope you suggested - in this case 'onRequestScope'. A lot more to say about IoC but not the scope of the question
I have used a similar pattern in the past and in my case I actually inherited from DbContext, which itself implements IDisposable. Provided you are using EFRepository or classes derived from it in a using block you should be fine.
If you would prefer a DbContext member variable, then EFRepository will need to implement IDisposable and call DbContext.Dispose() from its Dispose method.
Using SQLSERVER 2008R2, VisualStudio 2010, .NET 4.0
I'm getting this periodic exception: "Server failed to resume the transaction - Desc 2000003" (number changes)
Reading online forums and here, I found the main cause is to properly instance and close the Connections.
What should my classes look like?
Create the DataContext on Class level and use it on all methods?
public class BusProcess
{
RENDBDataContext db = new RENDBDataContext();
public void Insert()
{
//Do stuff here...
db.InsertProcedure(...);
}
}
Create and dispose a new DataContext on each method through using() ?
public class BusProcess
{
public void Insert()
{
using(RENDBDataContext db = new RENDBDataContext())
{
//Do stuff here...
int sample = db.SomeObject.SingleOrDefault(...).Id;
db.InsertProcedure(...);
}
}
}
Or maybe a different approach (Best practice)
Generally speaking, the lifetime of a DataContext instance should be bound to a single unit of work -- which is exemplified by your second usage.
The first usage can also be fine, depending on how long-lived the enclosing class is -- but whatever the case there, ensure that class implements IDisposable, dispose of the enclosed DataContext in your implementation of Dispose(), and wrap usages of that class with using().
Second approach is better than having DataContext around all time. It will prevent memory consumption when calling Load etc. Also remember that connections are pooled, so creating new DataContext is not a big deal.
A combination of both. Use the first method but have your classes implement IDisposable and call dispose on the context in your classes dispose method. You then use your classes in using statements. You could also pass in a DataContext in a constructor of your class for added flexibility.
I have found on the Internet an article which presents how to implement repository pattern. The implementation looks similar like here:
class ProductRepository : IProductRepository
{
var context;
public ProductRepository() {
this.context = new MyDataBaseDataContext();
}
// the rest of methods
}
But Im not quite sure is this right, what is happened with context? Is the Garbage Collector dispose this object? Or better should I create context with using (...) { } statement?
Repository should not open a data context, DataContext must be passed to it - since it must not own it. Let's say you have an operation which needs to be in a transaction and involves multiple repositories, what would you do?
You need to use UnitOfWork pattern.
In this pattern, a UoW (which wraps a DataContext) is passed to a repository.
Practically, ProductManager in Business layer creates a Unit Of Work.
The simple answer to this question is that the repository should be sure to dispose the data context itself, rather than letting it be finalized by the .NET runtime. This can be achieved by following the standard .NET dispose pattern...
class ProductRepository : IProductRepository, IDisposable
{
var context;
public ProductRepository() {
this.context = new MyDataBaseDataContext();
}
// the rest of methods
public void Dispose()
{
if (context != null)
{
context.Dispose();
context = null;
}
}
}
I guess it depends on whether you need transactions across repository operations and your need for tracking changes. The data datacontext can be immensely helpful since it can let you retrieve a bunch of objects, modify them in the application and then simply call SubmitChanges /RollbackChanges at any time you see fit. But if you don't expose this functionality in your repository you are probably better off by just "using" an instance in each repository method since this will preserve memory usage and resources for tracking changes.