What behavior should I use for a provider pattern with entity framework?
public class TestProvider : IDisposable
{
public Entities entities = new Entities();
public IEnumerable<Tag> GetAll()
{
return entities.Tag.ToList();
}
public ...
#region IDisposable Members
public void Dispose()
{
entities.Dispose();
}
#endregion
}
Or is it ok to use:
public class TestProvider
{
public IEnumerable<Tag> GetAll()
{
using (var entities = new Entities())
{
return entities.Tag.ToList();
}
}
public ...
}
Does it implies on performance? What are the pros and cons about it?
It depends on how long should TestProvider exist and what operations do you want to perform on retrieved entities. Generally ObjectContext instance should be used for the shortest time as possible but it should also represent single unit of work. ObjectContext instance should not be shared. I answered related question here.
It means that both your approaches are correct for some scenarios. First approach is ok if you expect to retrieve entities, modify them and the save them with the same provider instance. Second approach is ok if you just want to retrieve entities, you don't want to immediately modify them and you don't want to select anything else.
Related
I have these POCO classes, they're mapped using Fluent API with a TPT (Table per Type) strategy.
public class Base
{
...
}
public class Derived : Base
{
...
public virtual ICollection<Foo> Foos {get; set;} // One-to-Many
}
public class Foo
{
...
public virtual ICollection<Bar> Bars {get; set;} // One-to-Many
}
public class Bar
{
...
}
My repository looks like this.
public class Repo
{
public void Update(Base item)
{
using (var ctx = new DbContext())
{
ctx.Entry(item).State = EntityState.Modified;
ctx.SaveChanges();
}
}
}
Action:
public void DoStuff()
{
Derived item = repo.GetById(1);
item.SomeProp = "xyz"; // new value
item.Foos = GenerateFoosWithBars(); // change children
repo.Update(item);
}
To my surprise Update actually works if I'm only updating the Base or Derived classes. However things turn ugly when I try to update the One-to-Many relations. I found a tutorial on how to Update One-to-Many Entities in EF4. I was really expecting EF to be way smarter then this, I mean I have to do it manually... that's so unlike everything else in EF.
So I started out trying to use Entry cause I wanted it to be generic (being able to update any Base derived class) using Entry.OriginalValues to avoid having to write a query myself. But now shit really hits the fan! Entry.OriginalValues fails with an exception saying that DbSet<Derived> doesn't exists. It's totally right, it doesn't. But it shouldn't as the the Derived is mapped to DbSet<Base> via inheritance.
Clearly I must be doing something wrong or something so different from everyone else as I'm unable to find anything useful on the matter. Haven't EF5 improved on this in anyway?
Any suggestions on how I could approach this problem?
Firstly, I think an Update method is not necessary in the Repository since EF tracks changes and applies then when you call SaveChanges() on the context.
Secondly, the problem might be that you're assigning a new collection to the Foos poperty when yo do: item.Foos = GenerateFoosWithBars(); You shouldn't do that since when EF materializes an object of the Derived type it actually returns a proxy which overrides the virtual Foos collection to use a special kind of lazy loaded collection that it tracks. If you assign a different collection of your own that will not be bound to the context. (I don't think that EF will handle that very well). What you should do is modify the collection items not the collection itself! Hope it helps!
I know that the title looks a bit bad :) But I dont know how to explain my problem..
This is typically a basic problem for me but I dont know answer..
I am writing a server application which is using eneter library for client-server communinication and also it has a DAL gets data from database. as it a server application, it always need to communicate with database, so I dont know which way is more effective. (approx, max 50 clients will be connected to server)
I am using entity framework and created a model from my mysql db.
the first code is here
private MyEntities ent;
public DbHelper()
{
ent = new MyEntities();
}
void Foo()
{
ent.Mytable.where......
....
}
and second type code is
void Foo()
{
using (MyEntities ent = new MyEntities())
{
ent.Mytable.where...
}
}
Can I use using statement or create a global instance variable for dal class and use it for each functions.. ?
Better yet, implement IDisposable on your DAL class:
public sealed class MyDal implements IDisposable
{
private MyEntities ent = new MyEntities();
void Foo()
{
ent.Mytable.where......
....
}
public void Dispose()
{
ent.Dispose();
}
}
Then...
using(var dal = new MyDal())
{
dal.Foo();
//....
}
Take a read here about why my IDisposable is sealed.
From performance viewpoint it doesn't matter. Compared to the actual database interaction creating a context instance is a very fast operation.
However, you should dispose the created context in any case because it holds a database connection as a native resource.
If your want to work with a context member in your DbHelper class this class should implement IDisposable so that you can dispose the context when the DbHelper instance itself gets disposed:
public class DbHelper : IDisposable
{
private MyEntities ent;
public DbHelper()
{
ent = new MyEntities();
}
public void Foo()
{
//...
}
public void Bar()
{
//...
}
public void Dispose() // implementation of IDisposable
{
ent.Dispose();
}
}
You could use this class in a using block then:
using (var helper = new DbHelper())
{
helper.Foo();
helper.Bar();
} // helper and helper.ent gets disposed now
This depends on what other methods exist and what they do. If you want to make changes and persist those changes using the ORM, you will need the data-context that created the objects. Also, if you want the identity manager to give you the same object instance if you query the same thing twice, you will need to use the same data-context - so you'll need to keep it handy. Finally, if the type uses lazy loading and you expect it to work - then that won't work if you have disposed the data-context.
If, however, you just want read-only access to the data without change tracking, lazy loading or identity management : dispose eagerly. And maybe consider things like micro-ORMs which simply don't have those features (deliberately, to be minimal and fast).
The 2 approaches are very different in terms of the scope of the change-tracking. If both work equally well then make sure to use WithNoTracking.
You can create a member variable for your entities like in your first code. But because you cannot write a using(){} statement around it the containing class should be IDisposable. And then the consuming class should use it inside a using(){}.
I’m using Linq to Entities and lately, I found that a lot of folks recommending wrapping the datacontext in a using statement like this:
Using(DataContext db = new DataContext) {
var xx = db.customers;
}
This makes sense. However, I’m not sure how to incorporate this practice in my model.
For example: I have an interface (let’s call it customer) and it is implemented by a repository like this:
namespace Models
{
public class rCustomer : iCustomer
{
readonly DataContext db = new DataContext();
public customer getCustomer(Guid id)
{
return db.customers.SingleOrDefault(por => por.id == id);
}
public iQueryable<customer> getTopCustomers()
{
return db.customers.Take(10);
}
//*******************************************
//more methods using db, including add, update, delete, etc.
//*******************************************
}
}
Then, to take the advantage of using, I will need to change the methods to look like this:
namespace Models
{
public class rCustomer : iCustomer
{
public customer getCustomer(Guid id)
{
using(DataContext db = new DataContext()) {
return db.customers.SingleOrDefault(por => por.id == id);
}
}
public iQueryable<customer> getTopCustomers()
{
using(DataContext db = new DataContext()) {
return db.customers.Take(10);
}
}
//*******************************************
//more methods using db
//*******************************************
}
}
My question is: the recommendation of using “Using” is really that good? Please take in consideration that this change will be a major one, I have about 25 interfaces/repository combos, and each has about 20-25 methods, not to mention the need to re-test everything after finish.
Is there other way?
Thanks!
Edgar.
You can implement a Database factory which will cause your DbContext is being reused.
You can achieve this as follows:
DatabaseFactory class:
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private YourEntities _dataContext;
public YourEntities Get()
{
return _dataContext ?? (_dataContext = new YourEntities());
}
protected override void DisposeCore()
{
if (_dataContext != null)
_dataContext.Dispose();
}
}
Excerpt of the Repository base class:
public abstract class Repository<T> : IRepository<T> where T : class
{
private YourEntities _dataContext;
private readonly IDbSet<T> _dbset;
protected Repository(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
_dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get;
private set;
}
protected YourEntities DataContext
{
get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); }
}
Your table's repository class:
public class ApplicationRepository : Repository<YourTable>, IYourTableRepository
{
private YourEntities _dataContext;
protected new IDatabaseFactory DatabaseFactory
{
get;
private set;
}
public YourTableRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
{
DatabaseFactory = databaseFactory;
}
protected new YourEntities DataContext
{
get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); }
}
}
public interface IYourTableRepository : IRepository<YourTable>
{
}
}
This works perfectly together with AutoFac constructor injection as well.
Considering the code provided I see, you esplicitly use readonly DataContext db = new DataContext(); like a global variable, so you consider to have that object lifetime along with your rCustomer class instance lifetime.
If this is true, what you can do, instead of rewriting everything, you can implement IDisposable and inside Dispose() code something like
private void Dispose()
{
if(db != null)
db.Dispose();
}
Hope this helps.
As others have mentioned, it's important for the data contexts to be disposed. I won't go into that further.
I see three possible designs for the class that ensure that the contexts are disposed:
The second solution you provide in which you create a data context within the scope of each method of rCustomer that needs it so that each datacontext is in a using block.
Keep the data context as an instance variable and have rCustomer implement IDisposable so that when rCustomer is disposed you can dispose of it's data context. This means that all rCustomer instances will need to be wrapped in using blocks.
Pass an instance of an existing data context into rCustomer through its constructor. If you do this then rCustomer won't be responsible for disposing of it, the user of the class will. This would allow you to use a single data context across several instances of rCustomer, or with several different classes that need access to the data context. This has advantages (less overhead involved in creating new data contexts) and disadvantages (larger memory footprint as data contexts tend to hold onto quite a lot of memory through caches and the like).
I honestly think option #1 is a pretty good one, as long as you don't notice it performing too slowly (I'd time/profile it if you think it's causing problems). Due to connection pooling it shouldn't be all that bad. If it is, I'd go with #3 as my next choice. #2 isn't that far behind, but it would likely be a bit awkward and unexpected for other members of your team (if any).
The DataContext class is wrapped in a Using statement because it implements the IDisposable interface.
Internal to the DataContext it is using SqlConnection objects and SqlCommand objects. In order to correctly release these connection back to the Sql Connection Pool, they need to be disposed of.
The garbage collector will eventually do this, but it will take two passes due to the way IDisposable objects are managed.
It's strongly encouraged that Dispose is called and the Using statement is a nice way to do this.
Read these links for more indepth explanation:
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2625b105-2cff-45ad-ba29-abdd763f74fe/
http://www.c-sharpcorner.com/UploadFile/DipalChoksi/UnderstandingGarbageCollectioninNETFramework11292005051110AM/UnderstandingGarbageCollectioninNETFramework.aspx
An alternative would be to make your rCustomer class implement IDisposable, and then in your Dispose method, you can call Dispose on your DataContext if it is not null. However, this just pushes the Disposable pattern out of your rCustomer class, into whatever types are using rCustomer.
I am fairly new to .NET C# development and recently started using LINQ to SQL for the majority of my data access layer. Unfortunately, I have been struggling with how to manage my DataContext so that I don't get the dreaded exceptions that result from entities either not being attached to a context or attempting to attach an entity to one context while it is attached to another. After much reading, I believe that the best solution for my application is to leave the DataContext open for the entire duration of my application.
In short, I am using the Repository pattern to implement the basic CRUD operations (i.e. Create, Read, Update, and Destroy) for all entities managed by my context. My implementation of the Repository is included below. In addition to the Repository, I have DAOs (Data Access Objects) for each entity that has more specific data access methods (i.e. CustomerDAO.getCustomerByName(string name), etc...). Each of my Windows forms has its' own instance of one or more DAOs (that extend Repository) and the DataContext in my repository is static. The problem that I am running into is that even though my DataContext in the repository class below is declared as static, I'm finding that each distinct DAO actually gets a different instance of the DataContext. For example, if I have 8 references to the CustomerDAO, they all have the same DataContext. But, if I create one WorkOrderDAO I get another instance of the DataContext and all future instances of WorkOrderDAO get this same DataContext. More specifically, I discovered this in the following scenario.
1) Use an instance of WorkOrderDAO to load all WorkOrders into ListView - Has one DataContext
2) Use an instance of WorkOrderJobsDAO to attempt to delete one of the jobs on the WorkOrder. This is a collection on the WorkOrder. Has a different DataContext so I can't attach
Is this a problem with how I have implemented the Repository below? The only thing that I can think of to solve this issue is to create a Singleton that the Repository uses to get its' DataContext. Can anyone make any recommendations here for how I should manage the Context?
public class Repository<T> : IRepository<T>
where T : class
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
protected static DomainClassesDataContext db = new DomainClassesDataContext();
private static bool dataContextOptionsInitialized = false;
public Repository()
{
if (!dataContextOptionsInitialized)
{
db.DeferredLoadingEnabled = true;
dataContextOptionsInitialized = true;
}
}
public void AddEntity(T entity)
{
GetTable.InsertOnSubmit(entity);
SaveAll();
}
public void DeleteEntity(T entity, bool attach)
{
if(attach)
GetTable.Attach(entity);
GetTable.DeleteOnSubmit(entity);
SaveAll();
}
public void UpdateEntity(T entity, bool attach)
{
if(attach)
GetTable.Attach(entity, true);
SaveAll();
}
public System.Data.Linq.Table<T> GetTable
{
get { return db.GetTable<T>(); }
}
public IEnumerable<T> All()
{
return GetTable;
}
public void SaveAll()
{
db.SubmitChanges();
}
}
Generic classes in C# gets "expanded" on compilation, so your Repository will be a different class than Repository, which is why the static variables are different instances between your DTOs. So yes you probably want to save it somewhere else, like a in a Singleton class.
I have a 'Customer' POCO entity within my Entity Framework 4 project. I want to expose my Customer entities to my upper layers as a generic list rather than an ObjectSet.
I have an IUnitOfWork interface which looks as follows:
public interface IUnitOfWork
{
string Save();
IList<Customer> Customers { get; }
}
Down at my Entity Framework DAL (which implements the above interface) I have the following:
public class EntityContainer : ObjectContext, IUnitOfWork
{
private IObjectSet<Customer> _customers;
public IList<Customer> Customers
{
get
{
if (_customers == null)
{
_customers = CreateObjectSet<Customer>("Customers");
}
return _customers.ToList<Customer>() ;
}
}
}
However the 'CreateObjectSet("Customers")' line doesn't work. Every time I try to add a new 'Customer' nothing happens. Interestingly, if I revert to using an IObjectSet then the code works. For example:
public interface IUnitOfWork
{
string Save();
IObjectSet<Contact> Contacts { get; }
}
public class EntityContainer : ObjectContext, IUnitOfWork
{
private IObjectSet<Customer> _customers;
public IObjectSet<Customer> Customers
{
get
{
if (_customers == null)
{
_customers = CreateObjectSet<Customer>("Customers");
}
return _customers;
}
}
}
IQueryable also works, but I cannot get IList to work and I have no idea why. Anyone any ideas?
#
A correction to the original question. Using IQueryable doesn't work, nor does IEnumerable. This is because the Customer repository needs to provide 'Add' and 'Delete' methods to add/delete from the entity collection (add or remove customer entities in the above example). Neither IQueryable or IEnumerable allow you to add or remove objects; instead, an ICollection or IList must be used. This leaves me back at my original problem. I do not want to expose my collection to the repository as an ObjectSet. I want to use a type which is not tied to the EntityFramework i.e. - I want to use a generic list.
Has anyone any more suggestions? I suspect there's a straightforward way of doing this, but I'm not familiar enough with the framework to figure it out.
You seem to be missing a Repository in all of this. The Repository is usually what handles the conversion from ObjectSet<T> to IList<T> (or, in most cases, IEnumerable<T> or IQueryable<T>).
public class EntityContainer : ObjectContext
{
private IObjectSet<Customer> _customers;
public IObjectSet<Customer> Customers
{
get
{
return _customers ??
( _customers = CreateObjectSet<Customer>("Customers");
}
}
}
public class CustomerRepository
{
EntityContext _context = new EntityContext();
public IQueryable<Customer> FindAll()
{
return _context.Customers;
}
public Customer FindById(int id)
{
return _context.Customers.Single(c => c.Id == id);
}
// And so on.
}
I usually then have my UnitOfWork create the Repositories that should be enlisted in the Unit of Work so that anything done through the repositories is bundled in a single operation.
Keep in mind, that my UnitOfWork only would have two methods. One for getting a repository and another for committing the Unit of Work. All data retrieval is handled by the Repositories.
_customers.ToList() is the culprit. ToList executes the query and copies all the items from that query into a new collection object. this new collection object does not provide the tracking capabilities that ObjectSet has.