I'm trying to turn on use of cached entity models (after reading https://mirkomaggioni.com/2018/01/06/performance-improvements-in-entity-framework-6-2/) along with Npgsql provider.
dbconfiguration:
Class NpgsqlConfiguration
Inherits System.Data.Entity.DbConfiguration
Public Sub New()
Dim provider = "Npgsql"
SetProviderServices(provider, Npgsql.NpgsqlServices.Instance)
SetProviderFactory(provider, Npgsql.NpgsqlFactory.Instance)
SetDefaultConnectionFactory(New Npgsql.NpgsqlConnectionFactory())
SetModelStore(New DefaultDbModelStore(Directory.GetCurrentDirectory()))
End Sub
End Class
At the first run Edmx model is generated, with valid content.
However on the second run exception occurs, when i try to get access to some db sets from the context
ctx.Set(Of EntityClass).ToList()
System.ArgumentException: 'The path is not of a legal form.'
How can i overcome this? Thanks for the help.
Entity framework 6.2.0, Ngpsql 4.0.2, ef.npgsql 3.2.0
I'm using Costura.Fody for the solution, and when i've disabled it, EF started to load the generated model.
Hovewer I've didn't notice any significant performance boost :/
calling the first query with no edmx model takes about 2.4s
calling the first query with edmx model takes about 2.2s
I have 46 entities (tables) in the model, may be it is too small amount to find the effect of caching..
Related
I am using the Entity Framework POCOs to assist with migrating data from a legacy database to a new database. Both databases already exist and the Entity Framework has no part in creating or modifying structure for either. I created a sample database on the migration server and restored it to my local computer sql server (entirely in t_sql, no EF) and my context and its data classes are working fine and returning the data I want. Today I went to the production migration server and when I go to run my first test I get the above referenced error.
All I am doing is reading data, no writing, so this makes no sense to me. EF must be doing something when it hooks up the data context that I can't see. The error is coming from SqlClient.SqlConnection. There is no inner exception, no help link and nothing in the call stack except my method
Any ideas where to start looking?
Pamela
So it turns out the Entity Framework gets mad when the database changes at any point. You need to tell it to ignore the database. I did it by creating this base class for my data contexts
enter code here public class BaseContext<TContext> : DbContext where TContext : DbContext
{
protected BaseContext()
: base("Foxpert.HS.ChangeDetection.VHSContext")
{
Database.SetInitializer<TContext>(null);
Configuration.AutoDetectChangesEnabled = false;
}
}
I'm using the SQLite provider for Entity Framework 5 but it doesn't support CreateDatabase and thus cannot auto create the database. (Code First)
Is there a way I can obtain the Model schema at runtime so that I can create the SQL "CREATE TABLE" command myself?
If not at runtime, some other way to obtain the schema so I know how to create the table properly?
Thanks!
A) As for obtaining the model schema at runtime part
(all are earlier posts of mine)
See this one How I can read EF DbContext metadata programmatically?
And How check by unit test that properties mark as computed in ORM model?
Also this one for a custom initializer Programmatic data transformation in EF5 Code First migration
Having said that...
The problem I see is where and at what point you actually have the data available.
Actually I'm quite sure you won't be able to do that at any time.
Because to be able to extract that info you need to have a DbContext running - so db has to be constructed etc. etc.
In the initializer maybe - but using different ways to get that info - the above is not available.
B)
The other way would be to go the way of implementing a provider, generator etc. (e.g. this post).
That way you should get all that info just at the right time from the EF/CF itself.
However I haven't played with that much.
For more info you can check the EF source code
This is more of a 'gathered info' so far - in case it helps you get anywhere with it. Not really a solution. I'll add some more tomorrow.
EDIT:
To get the real database metadata, look into the other DataSpace, this should get you to the right place...
(note: things tend to get less exact from here - as obviously there isn't the right official support)
var ssSpaceSet = objectContext.MetadataWorkspace.GetItems<EntityContainer>(DataSpace.SSpace).First()
.BaseEntitySets
.First(meta => meta.ElementType.Name == "YourTableName");
If you look up in debugger, Table property should have the real table name.
However, reflection might be required.
How I can read EF DbContext metadata programmatically?
How check by unit test that properties mark as computed in ORM model?
Programmatic data transformation in EF5 Code First migration
Entity Framework MigrationSqlGenerator for SQLite
http://entityframework.codeplex.com/
Entity Framework - Get Table name from the Entity
ef code first: get entity table name without dataannotations
Get Database Table Name from Entity Framework MetaData
http://www.codeproject.com/Articles/350135/Entity-Framework-Get-mapped-table-name-from-an-ent
I an using EF5 Code First and needed a way to clear a table quickly. I therefore produced a very simple method to use ExecuteSqlCommand to provide a fast table clear. The code is below:
public void FastClearTable(Type tableType)
{
Context.Database.ExecuteSqlCommand(
string.Format("delete from {0}", PluraliseTableName(tableType.Name)));
}
I use this to clear a table before recalculating it. Below I have listed a simplified version of my method below. Note that the key of the table is a string (i.e. not an identity key) so I am putting in new entries with the same keys as the entries deleted by the ExecuteSqlCommand.
public int ComputeNewTableContent( IRepository<MyClass> rep, IUnitOfWork uow)
{
if ( rep.GetUntracked().Count() > 0)
uow.FastClearTable( typeof(MyClass));
--- compute new entries and call rep.Insert( newEntry) for each one ---
uow.Commit(); //This calls DbContext.SaveChanges()
}
This works fine the first time but if I run it again I get an exception on the SaveChanges() command, which is called by uow.Commit(). The exception is:
Message="Exception has been thrown by the target of an invocation."
InnerException Message="The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges."
If found this archived MSDN post and at the bottom the person had the same problem, but there wasn't an answer. My view is that the memory version of the data is still present and does not know about the ExecuteSqlCommand. However I don't don't know enough about EF yet to know how to fix it.
I can of course get round it by using a 'normal' delete but I would appreciate someone explaining what is going on and how I could handle it. That would improve my knowledge of Entity Framework.
Thanks in advance.
I hadn't found a good answer to my question on using ExecuteSqlCommand safely in entity framework until I came across Julia Lerman's excellent book 'Programming Entity Framework: DbContext'.
She covers the use of ExecuteSqlCommand (page 226) but most importantly she mentions using the Reload command after ExecuteSqlCommand to update the local (page 138). That updates the in-memory entity from the database. You use it as follows:
yourDbContext.Entry(TheTrackedEntityYouWantToUpdate).Reload();
This is exactly what I needed. Thanks Julia.
I my opinion Julia Lerman's DbContext book is a must for anyone planning a real-life application using Code First.
Are you using identity for your keys? Can it be that the ObjectContext is tracking old entities which you deleted from the database and are adding new entities. The new entities (if you don't have identity column for your key) are given the same keys as used by the old ones. Since the context is already tracking old entities it gets a new entity with a key of a tracked one. EF assumes that all changes are done through object context and not from the database. If you delete entities like this you should probably throw away the context
I'm using EF4, code first. As such, my model classes have a mix of public properties, some virtual properties (for lazy loaded data from other tables) and some properties that are affixed with [NotMapped] attributes so that they are skipped by EF.
Sometimes I like to make use of the raw query : c.Database.SqlQuery<T>("select ...") to use EF as a row mapper.
I noticed in Intellitrace that these queries were generating a lot of thrown and caught exceptions for "IndexOutOfRange". After some looking, the exceptions are all for the virtual and [NotMapped] properties on the model object. I don't want to have to construct a new data model class or parent class with just the table properties in it; is there some configuration step I've missed to tell the row mapper in the raw query runner to pay attention to the same annotations that the rest of EF uses? Maybe they fixed this in EF5?
If you execute dbContext.Database.SqlQuery EF will never use mapping. It will use just simple match of property names and columns in result set. Try to use dbSet.SqlQuery instead. It should reflect mapping because it can load data as attached entities.
I'm developing a data access layer for a database with over 700 tables. I created the model including all the tables, which generated a huge model. I then changed the model to use DBContext from 4.1 which seemed to improve how it compiled and worked. The designer didnt seem to work at all.
I then created a test app which just added two records to the table, but the processor went 100% in the db.SaveChanges method. Being a black box it was difficult to accertain what went wrong.
So my questions are
Is the entity framework the best approach to a large database
If so, should the model be broken down into logical areas. I did note that you cant have the same sql table in multiple models
I have read that the code only approach is best in these large cases. What is that.
Any guidance would be truly appreciated
Thanks
Large database is always something special. Any technology has some pros and cons when working with a large database.
The problem you have encountered is the most probably related to building the model. When you start the application and use EF related stuff for the first time EF must build the model description and compile it - this is the most time consuming operation you can find in EF. Complexity of this operation grows with number of entities in the model. Once the model is compiled it is reused for the whole lifetime of the application (if you restart the application or unload application domain the model must be compiled again). You can avoid this by precompiling the model. It is done at design time where you use some tool to generate code from the model and you include that code into your project (it must be done again after each change in the model). For EDMX based models you can use EdmGen.exe to generate views and for code first based models you can use EF Power Tools CTP1.
EDMX (the designer) was improved in VS 2010 SP1 to be able to work with large models but I still think the large in this case is around 100 entities / tables. In the same time you rarely need 715 tables in the same model. I believe that these 715 tables indeed model several domains so you can divide them into multiple models.
The same is true when you are using DbContext and code first. If you model a class do you think that it is correct design when the class exposes 715 properties? I don't think so but that is exactly what your derived DbContext looks like - it has a public property for each exposed entity set (in the simplest mapping it means one property per table).
Same entity can be used in multiple models but you should try to avoid it as much as possible because it can introduce some complexities when loading entity in one context type and using it in other context type.
Code only = code first = Entity framework when you define mapping in the code without using EDMX.
take a look this post.
http://blogs.msdn.com/b/adonet/archive/2008/11/24/working-with-large-models-in-entity-framework-part-1.aspx