I didn't know quite how to word this. I have an ASP.NET MVC 3 web application with a pretty standard EF 4.1 code first with existing database (non-auto-generated) repository pattern. There's a context which is under a dataservice the web app talks to.
The problem I have is this: say I have a database table with an integer column. The value is 10. If I go into the database itself and enter 25 into the table, no matter how many times I hit refresh on the browser, close the browser and reopen it, clear the browser history, etc, it still persists the value of 10. I have to republish the site.
Why does it do this? Am I blaming the right thing here? Is this an EF problem? an ASP.NET problem? Server problem? ... I don't know where to look into this.
Yes, I've struck this problem in my own applications.
The "entities" (object instances) tracked by Entity Framework are cached in memory, and aren't updated when you requery the database, in case overwriting them would clobber any changes you've made to the cached version.
You can get around it by forcing EF to overwrite existing values, but be aware that this will overwrite anything you've changed, so only do it if you know you've saved any pending changes first.
I've written this extension method to do the job:
public static class DbSetExtensions
{
public static System.Data.Objects.ObjectSet<T> Uncached<T>(this IObjectContextAdapter context)
where T : class
{
var set = context.ObjectContext.CreateObjectSet<T>();
set.MergeOption = System.Data.Objects.MergeOption.OverwriteChanges;
return set;
}
}
So using that, I can say:
var orders = myDbContext.Uncached<Order>().Where(...);
... and the orders set will contain orders that are fresh from the database, overwriting the properties of any Order objects previously queried.
Related
I have an MVC web application with code-first Entity Framework. We install this application in various computers as a local application. I made a migration to upgrade the database (in this case I added a new table), and after running the migration on upgrade, I want to insert initial data to the database so the users will be able to add/edit/delete them but I don't want the table to be empty at the first time.
Is there a way to do it automatically on upgrade without running a SQL script manually?
Migration class has up method,you can override it and insert/update records using SQL :
public override void Up() {
AddColumn("dbo.Posts", "Abstract", c => c.String());
Sql("UPDATE dbo.Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
}
(Source)
Yes there is. You essentially write a class to conditionally check and insert values, and then you link this class to your entity framework database initialiser. It runs each time there is a migration to be performed, but I think you can change exactly when it runs (e.g. Application startup).
This link will give you the rough idea:
Entity Framework Inserting Initial Data On Rebuild
I have an exact code sample on my PC but I won't be on it until tomorrow. If this link doesn't quite do what you want, I can send you some code tomorrow which definitely will.
I have a controller action where I am attempting to both create a new object in the database, of type FantasyTeam, and also modify an existing object, of type User. However, when the action is called I am receiving a System.InvalidOperationException exception, with the explanation of:
An entity object cannot be referenced by multiple instances of
IEntityChangeTracker.
My code is below.
public ActionResult Create([Bind(Include="ID,FantasyTeamName")] FantasyTeam fantasyteam)
{
if (ModelState.IsValid)
{
var CurrentUser = UserManager.FindById(User.Identity.GetUserId());
fantasyteam.OwnerID = CurrentUser.Id;
CurrentUser.HasTeam = true;
db.FantasyTeams.Add(fantasyteam);
db.Entry(CurrentUser).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Dashboard", "Application");
}
return View(fantasyteam);
}
The Controller Action takes the new FantasyTeam object as a parameter from the View where the team details are selected by user. I then find the currently logged in user and set the OwnerID of the team to match the UserID of the owner, as my Foreign Key. I then go to add the new FantasyTeam to the database and also modify the User record in the database, changing the Boolean HasTeam to true. The adding of the new team works fine on its own... I have been getting the exception once I tried to modify the User object as well.
I have searched on StackOverflow for this exception, and have found many related issues, but I couldn't find a way to apply the other resolutions to my problem. In some cases the issue was that the developers were using two separate data contexts when they should have just been using one, but I don't think that would apply to me here.
Could someone offer insight as to what might be going wrong here?
Thanks!
According to Linq to SQL DataContext Lifetime Management the main causality of the problem comes from the below reason.
Linq to SQL uses a DataContext to manage it's access to the database as well as tracking changes made to entities retrieved from the database. Linq to SQL has a persistent approach to managing its 'connection' to the database via this data context and it basically assumes that you use a single DataContext to make all of your data related access. This doesn't mean that it makes persistent connections to the database, but means that the DataContext instance maintains state about active result sets, which is especially important if change tracking is on which is the default.
The comment posted by haim770 was the answer - I didn't realize that the UserManager object was using a different context than the db object was using. Once I changed the UserManager object to use the same context as db, my code works as intended.
I have two databases that I am accessing. The first is against a contact database which I connected to using EF Model First; creating the edmx. I have since begun to learn the virtue of CODE First when working with Entity Framework, so I decided I would, in the same project, write the Product database using Code First techniques, allowing the database to be generated from the code I am writing.
Everything compiles fine. The problem occurs when I hit my harness and it attempts to create the Product database and retreive a list of values from one of the tables...
I get the folowing error "Could not find the conceptual model type for 'Core.Data.Account'", when I attempt to enumerate the ProductLines property (Line3 below).
1. using (var ctx = new ProductDb())
2. {
3. var lines = ctx.ProductLines.ToList();
4. this.litOne.Text = lines.Count.ToString();
5. }
After some research it appears that this message may be occuring because of multiple entities with the same name (regardless of namespace), however there is nothing in the ProductDb context with the name "Account".
There is a class in the OTHER context created by the Model First approach named "Account". But how/why would that make a difference? They each point to different databases i.e. different connection strings. Why would the ProductDb be attempting to create a table called Account, when it should be completely unaware of it's exstence?
thoughts?
Thank you as always!,
- G
I bumped into the same problem, but the other way around: first a DbContext + generated database and then generated an edmx off the database (just for a little presentation). It appeared to be a restriction in EF: EF currently has a restriction that POCO classes can't be loaded from an assembly that contains classes with the EF attributes.
The only thing you can do for now is keep the contexts in separate assemblies.
My application is using EF code-first design and all generally works very well.
Via a private configuration file, I can specify how I would like EF to handle changes to the db schema, and so create/recreate the relevant tables as desired - the options are "never" "create", "always", "onSchemaChanged" and (for the future) "onSchemaModified".
This works well - but I am getting lost in a couple of places .....
During development, I would like to use the hook as described in
"Database in use error with Entity Framework 4 Code First" - but this seems to execute on EVERY run of my program"
public void InitializeDatabase(Context context)
{
context.Database.SqlCommand("ALTER DATABASE Tocrates SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
_initializer.InitializeDatabase(context); // Maybe this does nothing if not needed
context.Database.SqlCommand("ALTER DATABASE Tocrates SET MULTI_USER")
}
So .. to real my question: Is there an override that I can use to detect whether EF will ACTUALLY be trying to modify the database, so I can set this SINGLE_USER stuff when needed? And if so, can I detect the reason EF it is doing so (see my list of options above) so I can log the reason for change?...
All help and suggestions are very much appreciated.
Unless you have set the database intializer to null initializers run always once (per application lifetime) when you are using a context for the first time. What then actually happens depends on the initializer (your inner _intializer):
For DropCreateDatabaseAlways and CreateDatabaseIfNotExists it's clear by their name what they do.
For DropCreateDatabaseIfModelChanges there is only the question if the model changed or not. EF detects this by comparing a model hash with a hash stored in the database. You can check this yourself by calling...
bool compatible = context.Database.CompatibleWithModel(true);
...within your custom InitializeDatabase and then decide based on the result if you want to send your SqlCommands or not. (Don't call this with a self-created context because it will cause the database to be intialized first before the model compatibilty is checked.) The parameter bool throwIfNoMetadata (which is true in my example) causes EF to throw an exception if the model hash in the database does not exist. Otherwise the method will return true in that case.
For a custom inner initializer: Whatever your code will do.
Let's start with this basic scenario:
I have a bunch of Tables that are essentially rarely changed Enums (e.g. GeoLocations, Category, etc.) I want to load these into my EF ObjectContext so that I can assign them to entities that reference them as FK. These objects are also used to populate all sorts of dropdown controls. Pretty standard scenarios so far.
Since a new controller is created for each page request in MVC, a new entity context is created and these "enum" objects are loaded repeatedly. I thought about using a static context object across all instances of controllers (or repository object).
But will this require too much locking and therefore actually worsen perf?
Alternatively, I'm thinking of using a static context only for read-only tables. But since entities that reference them must be in the same context anyway, this isn't any different from the above.
I also don't want to get into the business of attaching/detaching these enum objects. Since I believe once I attach a static enum object to an entity, I can't attach it again to another entity??
Please help, I'm quite new to EF + MVC, so am wondering what is the best approach.
Personally, I never have any static Context stuff, etc. For me, when i call the database (CRUD) I use that context for that single transaction/unit of work.
So in this case, what you're suggesting is that you wish to retrieve some data from the databse .. and this data is .. more or less .. read only and doesn't change / static.
Lookup data is a great example of this.
So your Categories never change. Your GeoLocations never change, also.
I would not worry about this concept on the database/persistence level, but on the application level. So, just forget that this data is static/readonly etc.. and just get it. Then, when you're in your application (ie. ASP.NET web MVC controller method or in the global.asax code) THEN you should cache this ... on the UI layer.
If you're doing a nice n-tiered MVC app, which contains
UI layer
Services / Business Logic Layer
Persistence / Database data layer
Then I would cache this in the Middle Tier .. which is called by the UI Layer (ie. the MVC Controller Action .. eg. public void Index())
I think it's important to know how to seperate your concerns .. and the database stuff is should just be that -> CRUD'ish stuff and some unique stored procs when required. Don't worry about caching data, etc. Keep this layer as light as possible and as simple as possible.
Then, your middle Tier (if it exists) or your top tier should worry about what to do with this data -> in this case, cache it because it's very static.
I've implemented something similar using Linq2SQL by retrieving these 'lookup tables' as lists on app startup and storing them in ASP's caching mechanism. By using the ASP cache, I don't have to worry about threading/locking etc. Not sure why you'd need to attach them to a context, something like that could easily be retrieved if necessary via the table PK id.
I believe this is as much a question of what to cache as how. When your are dealing with EF, you can quickly run into problems when you try to persist EF objects across different contexts and attempt to detach/attach those objects. If you are using your own POCO objects with custom t4 templates then this isn't an issue, but if you are using vanilla EF then you will want to create POCO objects for your cache.
For most simple lookup items (i.e numeric primary key and string text description), you can use Dictionary. If you have multiple fields you need to pass and back with the UI then you can build a more complete object model. Since these will be POCO objects they can then be persisted pretty much anywhere and any way you like. I recommend using caching logic outside of your MVC application such that you can easily mock the caching activity for testing. If you have multiple lists you need to cache, you can put them all in one container class that looks something like this:
public class MyCacheContainer
{
public Dictionary<int, string> GeoLocations { get; set; }
public List<Category> Categories { get; set; }
}
The next question is do you really need these objects in your entity model at all. Chances are all you really need are the primary keys (i.e. you create a dropdown list using the keys and values from the dictionary and just post the ID). Therefore you could potentially handle all of the lookups to the textual description in the construction of your view models. That could look something like this:
MyEntityObject item = Context.MyEntityObjects.FirstOrDefault(i => i.Id == id);
MyCacheContainer cache = CacheFactory.GetCache();
MyViewModel model = new MyViewModel { Item = item, GeoLocationDescription = GeoLocations[item.GeoLocationId] };
If you absolutely must have those objects in your context (i.e. if there are referential entities that tie 2 or more other tables together), you can pass that cache container into your data access layer so it can do the proper lookups.
As for assigning "valid" entities, in .Net 4 you can just set the foreign key properties and don't have to actually attach an object (technically you can do this in 3.5, but it requires magic strings to set the keys). If you are using 3.5, you might just try something like this:
myItem.Category = Context.Categories.FirstOrDefault(c => c.id == id);
While this isn't the most elegant solution and does require an extra roundtrip to the DB to get a category you don't really need, it works. Doing a single record lookup based on a primary key should not really be that big of a hit especially if the table is small like the type of lookup data you are talking about.
If you are stuck with 3.5 and don't want to make that extra round trip and you want to go the magic string route, just make sure you use some type of static resource and/or code generator for your magic strings so you don't fat finger them. There are many examples here that show how do assign a new EntityKey to a reference without going to the DB so I won't go into that on this question.