I'm writing an ASP.NET MVC application with EF. I have some questions regarding whether or not my approach is reasonable. Note: I simplified my basic structure for this question, in realitiy everything is coupled more loosely.
Let's assume a View that allows a user to change properties of a complex domain model. The data originates from the Database (via EF) and has to be written back again in the end.
From my understanding, each request results in a new controller instance being called. Therefore, I'm using the 'Dispose Pattern' described here as Option 2, which ensures a new DbContext for every request:
public class MyController : Controller
{
private MyContext repo = new MyContext();
protected override void Dispose(bool disposing)
{
this.repo.Dispose();
base.Dispose(disposing);
}
//more code...
}
Now there is a public ActionResult Edit(elementId) method on the controller that will fetch an element from the database and displays an editor for it. Once this request is finished, any reference to the Dbcontext is gone, but I still have access to the Entity-Object fetched from the DB as I store it in my session.
Later on the user presses a 'Save' button on the View. The request to the Save-method of my Controller once again creates a new instance of the Controller and therefore a new DbContext. The Entity-object stored in my session is retrieved and its properties are modified according to the user's input. To save the new state to the database, I have to attach it to the new context:
public void Save()
{
this.repo.MyTable.Attach(myEntity);
myEntity.Name = "New Name";
this.repo.SaveChanges();
}
This can only work once the old Controller with the original DbContext of myEntity has been disposed, otherwise 'Attach' would fail (unable to attach Entity to two contexts). I'm concerned whether or not I can rely on the old DbContext being disposed here.
Also: I know that using an IoC framework would be an alternative. How would that apply to my situation, what would be the benefits?
I think you've redacted too much of your code in an effort to "simplify" the question, and as a result, have actually obscured some important issues. However, based on the Save method you've posted, I can pretty well guess your issue. Your repo is most likely creating it's own context, which is a pretty big no-no.
To answer you overall question, the rationale for implementing IDisposable here is the same as anywhere else: any class that owns dependencies that implement IDisposable should also implement IDisposable. Here, your controller instantiates MyContext, so it should therefore dispose of MyContext when its done. Simple as that.
However, if you introduce dependency injection, and inject the context into the controller, then the controller no longer owns the context. Instead, the DI container will own it. Therefore, your controller should not dispose of the context, as it does not own it.
And, you should use dependency injection here. Your context should be injected into your repository and then your repository should be injected into your controller. This ensures that there's is only one context instance, and you won't have issues like you're experiencing now, where EF complains that the entity belongs to a different context.
Finally, I just want to parrot #SteveGreene in saying that there is absolutely no reason to store your entity in the session, and in fact there's many reasons you shouldn't, not the least of which being it will frustrate any efforts to move away from In Proc sessions to a more reliable session store. Once you're using something like StateServer, SQL Server, Redis, etc., anything you put in the session must be serializable, and entities are often quite difficult if not impossible to serialize, since they often have many relationships with other entities and often circular relationships with those entities.
Related
Im new to C# and Entity Framework and I have a question about fields and initialization of a database class.
I have received some code in a program from my teacher that has a connection to a MySQL database through Entity Framework.
So far we have seen examples where inside methods for adding stuff to the database you first create an instance of it. An example of what we have seen so far:
using (var db = new p4_databaseEntities())
{
cp_car carEntity = new cp_car();
carEntity.make = car.make;
carEntity.model = car.model;
carEntity.year = car.year;
db.cp_car.Add(carEntity); //
db.SaveChanges();
MessageBox.Show("A Car has been added");
}
this.Close();
cp_car is a table in the database and a class in the program.
db is the current instance of the database.
Now, in the code I have received, this is not done this way. Its done in a different matter. Btw the program is a windows forms.
In the first form window, inside the constructor, he has created a new instance of the database and he calls upon a method called init
from the another class called LinqQueries. The code for that:
public Form1()
{
InitializeComponent();
p4_databaseEntities db = new p4_databaseEntities();
LinqQueries.Init(db);
this.CenterToScreen();
}
How the LinqQueries class looks:
private static p4_databaseEntities _db;
public static void Init(p4_databaseEntities db)
{
_db = db;
}
As I understand he created a new instance of the database in the constructor, where he also called on the init method. This method then defined the db object as _db. Now every single method he makes for adding or removing data from the database he is using _db and not db.
My question is does this mean that the init method assigns the static field of type p4_databaseEntities (name of database class) as an object? Is the value of the _db then an object? Is it a reference to an object? And also i noticed he uses the same field over and over again when making changes to the database which led me to believe it may be an active object that doesn’t die through out the programs lifespan?
If anyone could clarify this It would be greatly appreciated. Excuse any errors or wrong statements I have made please correct me if im wrong in any way. Im new to C# and Entity Framework.
Thanks beforehand
You are a bit inaccurate in your descriptions. This attributes to your confusion.
A DbContext is not a database, it represents the connection to the database. If you construct a DbContext object, you get access to the tables in the database via the Entities described in the DbSet.
Although it seems that a DbSet represents a table in the database, it does not. For instance an entity that you access via a DbSet can have an ICollection as member, which contains items that are not part of the table, but are items in a different table. Accessing the items in this ICollection causes an SQL Join to be performed, without you having to type the join
Hence a DbSet object in the DbConnection does not represent database table, it represents the access to the properties that can be accessed using the DbSet object, inclusive the properties of all objects in the database that are in tables that have a relation with the DbSet object.
Your first code with the using statement is the normal way entity framework should be used.
To hide the design of the database, quite often a separate class is introduced that is the only one that should use the DbContext. All users of the database should communicate using the seperate class.
This allows changing the internals of the database without having to change the code that uses the database.
This is what probably was meant as the purpose of the LinqQueries class. Instead of calling functions of the DbContext directly, users should call the (probably static) functions of LinqQueries. This way the internal structure of the database can change without having to change the callers of the LinqQueries functions.
What in fact is happening is that LinqQueries is meant to communicate with only one DbContext. LinqQueries does not decide which DbContext is used. Proper functioning depends heavily on exactly one user of LinqQueries who should create a DbContext and Init LinqQueries. This one user should also know when no one needs the LinqQueries anymore, because he has to Dispose() the DbContext.
This design if fairly error prone. Supposing the designer makes very grood products, his products will be used by a lot of users (meaning software, not operators). How do you assert that exactly one user will call the Init function?
If you really want that all users use the same Dbcontext, why not let the constructor of LinqQueries create this DbContext. In fact the design is similar to the singleton design pattern, so why not create LinqQueries as a singleton.
The limitation that all users of LinqQuery should use the same one and only DbContext limits the use of the LinqQuery class unnecessarily.
If users of the LinqQuery class could pass a DbContext to the constructor, then users could decide which database should be used by this particular LinqQueries object. This is quite handy when creating unit tests: instead of using the original database, the testable code could be used with a database with specific test values.
All in all the goal of the designer is unclear. IMHO it is a bad design and you are right that it is not clear what happens.
class LinqQueries
{
// default constructor: use the default DbContext
public LinqQueries()
{
this.DbContext = new p4_databaseEntities();
}
// special constructor: user provided dbContext
public LinqQueries(p4_databaseEntities dbContext)
{
this.dbContext = dbContext;
}
private readonly p4_databaseEntities dbContext;
public IEnumerable<...> GetMyElements(...)
{
return this.dbContext....;
}
}
This way, every creator of the LinqQueries would exactly know what to do either use the default p4_databaseEntities or create your own Dbcontext and dispose it when not needed anymore
using (var mydbContext = new p4_databaseEntities())
{
LinqQueries linqQueries = new LinqQueries(myDbContext);
// note that this constructor is very lightWeight!
var result = linqQueries.MyQeury(...);
}
This method is really safe. Any errors made by me, does not influence the code of any other user of the LinqQuery class.
So I am currently extending the classes that Entity Framework automatically generated for each of the tables in my database. I placed some helpful methods for processing data inside these partial classes that do the extending.
My question, however, is concerning the insertion of rows in the database. Would it be good form to include a method in my extended classes to handle this?
For example, in the Product controller's Create method have something like this:
[HttpPost]
public ActionResult Create(Product p)
{
p.InsertThisProductIntoTheDatabase(); //my custom method for inserting into db
return View();
}
Something about this feels wrong to me, but I can't put my finger on it. It feels like this functionality should instead be placed inside a generic MyHelpers.cs class, or something, and then just do this:
var h = new MyHelpers();
h.InsertThisProductIntoTheDatabase(p);
What do you guys think? I would prefer to do this the "correct" way.
MVC 5, EF 6
edit: the InsertThisProductIntoTheDatabase method might look something like:
public partial class Product()
{
public void InsertThisProductIntoTheDatabase()
{
var context = MyEntities();
this.CreatedDate = DateTime.Now;
this.CreatedByID = SomeUserClass.ID;
//some additional transformation/preparation of the object's data would be done here too. My goal is to bring all of this out of the controller.
context.Products.Add(this);
}
}
One of the problems I see is that the entity framework DBContext is a unit of work. if you create a unit of work on Application_BeginRequest when you pass it into controller constructor it acts as a unit of work for the entire request. maybe it's only updating 1 entity in your scenario, but you could be writing more information to your database. unless you are wrapping everything in a TransactionScope, all these Saves are going to be independent which could leave your database in an inconsistent state. And even if you are wrapping everything with a TransactionScope, I'm pretty sure that transaction is going to be promoted to the DTC because you are making multiple physical connections in a single controller and sql server isn't that smart.
Going the BeginRequest route seems like less work than adding methods to all of your entities to save itself. Another issue here is that an EF entity is supposed to be a not really know anything about it's own persistence. That's what the DbContext is for. So putting a reference back to the DbContext breaks this isolation.
Your second reason, adding audit information to the entity, again adding this to each entity is a lot of work. You could override SaveChanges on the context and do it once for every entity. See this SO answer.
By going down this road I think that you are breaking SOLID design principles because your entities violate SRP. introduce a bunch of cohesion and you are ending up writing more code than you need. So i'd advocate against doing it your way.
Why don't you simply use:
db.Products.Add(p);
db.SaveChanges();
Your code would be much cleaner and it will certainly be easier for you to manage it and get help in the future. Most of samples available in internet use this schema. Extension methods and entities does not look pleasnt.
BTW: Isn't InsertThisProductIntoTheDatabase() method name too long?
In a EF 6 project, I am writing validation functions for entities. some are static while others are instance methods of the entities themselves.
Ignoring whether this is bad practice or not, I'd like to check whether the entities were created using a context and if so, whether they are still attached.
Please note that these functions do NOT have access to the context object, just the entity classes.
As an example, a method validates Department entity and cascades validation to all associated Department.Employee instances.
If the hierarchy was created manually, validation will succeed.
If the hierarchy was created using a context which is still alive, validation will succeed albeit slower.
If the hierarchy was created using a context which has been disposed, validation will fail with an ObjectDisposedException (provided proxy-creation was enabled and .Include(***) was not used).
So the question, is it possible to detect the above scenarios without access to a DbContext instance? If not, how can we best validate entire hierarchies irrespective of how they were created.
var result = true;
var departments = ???; // Constructed manually or through a DbContext instance.
foreach (var department in departments)
{
result &= department.Validate();
foreach (var employee in department.Employees)
{
result &= employee.Validate();
}
}
EDIT: Please note that this is for a desktop application that cannot have long-running DbContext instances. they are almost always disposed immediately after retrieving data. Re-querying the database does not seem a viable option for validation since it is triggered by trivial user input and would slow down the entire user experience.
From your question
Please note that these functions do NOT have access to the context object, just the entity classes.
two solutions come to mind, none really palatable:
Build your own tracker and make it available to these methods somehow.
Add something to your entities, for example a WasLoaded property that gets set when you query your context. That WasLoaded could be set by either
Writing an EF interceptor that sets it.
Adding an artificial bit column with all values set to 1. Then map that to the property; the property will be false if you constructed it outside of the context, true if loaded from the context.
The tracker seems to be the cleanest because it doesn't pollute your model. The interceptor is a decent alternative if you're not concerned about your model.
And while it doesn't answer your question directly, you could avoid the use of proxies, in which case your validation works the same way regardless because you have your model in memory. There's the usual trade-offs to consider though.
I'm not sure how you'd detect the last scenario. I suppose you could have your tracker track more than the entities... have it also track the context's state.
I'm building a Webforms EF6 database first application and am not sure how best to manage DbContext. I looked at a lot of tutorials and forum posts but I'm still sure. Regarding the much favored 'using per request', I've not found a way to save parent & children in one go. I got it to work with the code below, but where and when would I dispose of the context? Can I use this approach? Would the per request approach by Kamyar shown here be better?
Here's what I've got now:
public static class ContextManager
{
[ThreadStatic]
private static MyContext current;
public static MyContext MyCurrentContext
{
get{
if (current == null)
current = new MyContext();
return current;
}}
}
coupled with
var context = ContextManager.MyCurrentContext;
.....
context.SaveChanges();
Thanks in advance for any help!
A specific example would be 'UserProfile' which contains child objects as properties such as 'DefaultInvoiceAddress' which returns the user's default invoice address from a table with all the user's addresses. In the last web application I worked on, when user edits this address from within the profile (e.g. street change), together with other profile information from other tables, EF would save all edited information from the different tables in one request (ensuring they're attached). Since I wasn't privy to the context management, I don't know how it was done, but we would always assign a common current context for the requests.
I came across this post by Rick Strahl, and this one by Jordan van Gogh - the business object / transaction seem to be an answer, but I don't quite understand how to implement it and couldn't find an example. The 'shared ObjectContext instance per HTTP request' corresponds to Kamyar's answer mentioned above, and all things considered, it sounds a good option. Would I have to explicitly dispose of the context, if so when/where?. Are there any drawbacks?
Bad idea. Static is totally against the best practices. No 2 users ever will use the app at the same time? Ouch. For WebForms.
Per request IS the best choice.
The EF db context object is not, I repeat NOT threadsafe no matter how you manage it. Lots of problems can arise from sharing a db context across threads so the best way is, as mentioned above to use it per request.
If you don't want to jump into the IoC/DI side of things a really simple way to do it is whenever you need the database you just instantiate your context in a using block, like so:
using(var db = new MyContext())
{
// code reading from/writing to database
...
...
}
Using singleton pattern with entity framework database context is a design defect specially if you work with concurrency environment such as web forms because you have to take in your consideration that DbContext is not thread safe object.
I have this code in my Controller:
public class MyController : Controller
{
private readonly IMyRepository myRepository;
public MyController() : this(new MyRepository())
{}
public MyController(IMyRepository myRepository)
{
this.myRepository = myRepository;
}
public ActionResult Index()
{
return View(myRepository.GetData());
}
}
MyRepository uses EF for data operations. Every time user loads this page instance of MyRepository is creating. That means EF context is creating and Fluent API code is executing (OnModelCreating method).
Are there any possibilities not to create EF context everytime when user loads the page?
MyRepository uses EF for data operations. Every time user loads this
page instance of MyRepository is creating. That means EF context is
creating and Fluent API code is executing (OnModelCreating method).
You're wrong. Put a breakpoint on your OnModelCreating method. This method will only get hit once, when your application loads. It will hit the breakpoint again if you rebuild the project, because this causes the binary dll to be reloaded into the app domain. However if you leave the application running and hit the controller action twice (without rebuilding in between), you will see that OnModelCreating does NOT get hit the second time. Like Serg Rogovtsev says, EF caches the model (meaning the schema) after it is created during OnModelCreating.
The only objection I have to Serg Rogovtsev's answer is that I would never create a singleton instance of the DbContext. Instead you should use one instance per HttpContext (a.k.a. per web request). If you use it as a singleton, and you have concurrency enabled, you would end up seeing DbConcurrencyExceptions creep up in your app. Use DI/IoC, and create/dispose the DbContext instance at the beginning/end of the request response cycle. That is the best practice. Don't worry about the overhead of creating a new MyDbContext() instance. After EF initializes (warms up) during the first construction, future constructions will be fairly cheap.
To answer your question: you can create a singleton of your repository or you can use DI container which will hold single instance for you.
But to the point: if you set breakpoint inside OnModelCreating you will find that it gets called only once per application instance. EntityFramework uses pretty effective model caching. So you don't have to worry about performance hit caused by creation of EF contexts.
Change your controller so you create an instance of your repository in a lazy way. You can use the Lazy < T > class for example.
In terms of performance I'd favour looking to persist data and not the context, the EF context is optimized to be created and then disposed to free up connections in the pool.
Some other EF performance methods at http://www.sql-server-performance.com/2012/entity-framework-performance-optimization/
Best practice is to dispose the EF context after you've retrieved/updated your data.