EntityFramework using wrong tablename - c#

My code is giving me an EntityCommandExecutionException when i'm trying getting data from my Bieren Table.
The exception message says that it can't find "dbo.Biers" which is quite obvious because it's called "dbo.Bieren".
I can quite easily fix this by just renaming the table in the database. Altough i don't like fixing my database around my code's errors.
How can i make the entity framework use the correct table instead of changing the name of my table?
Thanks in advance.

Decorate your entity class with the TableAttribute property, e.g.
[Table("Bieren")]

For the database-first approach, StriplingWarrior's solution works well. But if you use the code-first approach, you could use System.ComponentModel.DataAnnotations.TableAttribute on a target entity class to map an entity class to a database table.
However, this way is slightly annoying, because we commonly want to define a pure entity class. To do this, you could entrust it to another class or use the overrided OnModelCreating method in the DbContext class as the following.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Category>()
.ToTable("MyCategories");
}

Your Entity Framework model has information about the table names and connections that it is connecting to. If you're using a database-first approach, you should have an EDMX file with your database model in it. The easiest way is to update the model from the database.
Open the EDMX file in Visual Studio
Delete the incorrect "Biers" table
right-click in the background and click "Update Model from database"
Point the wizard at your database, and select the "Bieren" table to add
Finish the wizard, and the "Bieren" table should appear
It is also possible to dig into the properties of the Biers type, and manually change the table name.

Related

Entity Framework Core code-first perform additional actions when generating migrations

I want to keep a history of changes made to all of my tables generated by EF Core.
I could do this by manually creating a second model for every model I want duplicated, but I was wondering if there's any way to do this automatically somehow.
What I would want it to do is, every time a migration is generated that includes a CreateTable call, create a duplicate of the table with something like "History" appended to the name, and with an additional column relating to the original record.
I'm not sure what would be the best way to achieve this, as I'm not very experienced with ASP.NET yet. I was thinking of overriding the MigrationBuilder.CreateTable method, but I can't figure out how I'd get the actual migration builder to use my overridden method.
Note that SQL does support Temporal Tables which internally create a second table for you. It has start/end time columns instead of a single column. The database engine maintains this for you (meaning even ad hoc sql queries not through EF are properly tracked into the history table). This is part of the ANSI SQL standard so you might find this easier than rolling your own. You can read more about these on the MSFT documentation page
If I understand it correctly, you want to execute custom SQL script before running the migration.
Well, that is indeed possible.
You will generate the migration as you do now and you'll get something like this:
public partial class MyMigration: Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
//auto-generated mappings
}
}
before the auto-generate call, you could insert your own SQL script like this:
public partial class MyMigration: Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("CREATE TABLE Customers_History (CustomerName, City, Country)");
migrationBuilder.Sql("INSERT INTO Customers_History (CustomerName, City, Country) SELECT CustomerName, City, Country FROM Customers)");
//auto-generated mappings
}
}
This is just an example, but you can add your own SQL to match your scenario.
With this solution you are not required to create additional models.

How to set default values in Entity Framework 6 (Database First)

Background: I’m beginning a project to convert a web application using Linq2Sql to use Entity Framework (v6) instead. I have a lot of experience with L2S, but I’m brand-new to EF. Since our application and its database already exist, we’re using the “Database First” approach. Also, the database is evolving, so we’re making changes in the schema and the model is updated from the revised database, which regenerates code for the EF model each time.
For many of our entities (database tables), we set default values in our code whenever an entity is constructed. In Linq2Sql it’s easy: define a partial class for the entity, and add a method to the class like this:
partial void OnCreated() { SomeProperty = SomeDefaultValue; }
Whenever Linq2Sql constructs a new entity object, it calls the OnCreated() method you define, and the default values are set as desired. It works great.
The Problem: In EF, I don’t see a way to do this in a Database First scenario.
If I modify the model code generated by EF, the model code is overwritten whenever we update the model after a database revision.
If I define a partial class for the entity in a separate file and define a constructor, the compiler complains that the constructor is already defined.
There doesn’t seem to be any support for something like L2S's OnCreated() method, either.
Any suggestions?
EDIT: Thanks everyone for the helpful comments, but I think I need to point out an important consideration: My goal is to use the database-first approach and stick with it, rather than switching to code-first. When the database schema changes over time I want the EF Designer (or POCO Generator or whatever tools) to update my EF entity classes to match. All without losing my additions to initialize class properties when the class is constructed in the application. This is easy in Linq2Sql, but I just don’t see a way to accomplish this in EF database-first. All suggestions are welcome!
1 . Open .edmx file
2 . Select the field that has the default value and go to the properties
3 . then select StoreGeneratedPattern
4 . then change the value to Computed
i think it's worked.
OP here – I’ve given credit for the answer to ErikEJ but I’d like to recap what I’ve learned on this topic to share with others. There are three goals:
Use the database-first approach and stick with it, even as the database schema is changed over time. That is, have EF produce the code for each database table entity, based on a preexisting database, and update the code when the database is altered.
Provide a mechanism to initialize entity object properties each time the object is constructed, such as Employee.Dependents = 1, for example. (I know simple defaults can be set by the database schema, but more complex initializations must be executed by code.)
The custom initialization code must be preserved when the database schema is altered and EF regenerates the model code.
EF doesn’t provide a way to set properties each time an entity object is constructed in the database-first scenario. Editing the EF-generated code doesn’t work because it gets overwritten whenever EF regenerates the code after a change to the database schema. So far, four workarounds come to mind:
One idea is to add a constructor with more than the default zero-parameter constructor for each entity class. For example, c = new Customer(x) rather than the default c = new Customer(). Application code would call the new constructor, which would inherit the default constructor and add additional code to initialize the class properties. This avoids duplicating the default constructor, something that isn’t permitted by C#. The new constructor is in a separate partial class file, so it will not be overwritten when EF generates updated models from the database.
However, there is a risk that the application programmer may call the default constructor by accident, leading to subtle bugs.
Another solution is to wrap the entity classes in another class, say, a Customer2 class wrapped around the Customer class. The new class would inherit the original class and add initialization code for any properties as needed.
Since these new classes are separate from the original entity class code, they will not be overwritten by EF when it regenerates model code. It may be possible to hide the entity classes from the top-level application code, to avoid accidentally referring to the original classes by accident. If so, this should be a good technique, although I haven’t tested it yet.
A third-party tool, EntityFramework Reverse POCO Generator, is a help. It generates POCO model code much as EF does, but it is not EF. It has an option to generate partial classes, and the entity classes include a InitializePartial() method much like Linq2Sql’s OnCreated(). I think this will work fine for regenerating code as the database is altered over time. My concern here is that this is a third-party product, and there’s always a risk that it can become obsolete or unsupported.
Finally, you can alter the template that EF uses to generate code. The basic idea is to have the generated code add “partial void OnCreated()” to each class, and this lets us use the same convenient technique built into Linq2Sql. I assume newer versions of EF may overwrite the template changes, but it’s just one change in the template rather than changes to every entity class. This method is described here (How to efficiently set default entity values in Entity Framework 6, Database First) and the YouTube video is here (https://www.youtube.com/watch?v=i8J2ipImMuU).
Thanks to all who contributed! I hope this page is helpful to others, so you don’t have to burn as much time as I did looking for a solution.
Use the EF Reverse poco template- it will derive defaults from the database. You can override the InitializePartial method in your partial class to set defaults in code.
Coming from the EF background, I generally do it in the code first migration manually. In the up function of the generated migration, you can do something like this
AddColumn("dbo.Person", "IsActive", c => c.Boolean(nullable: false, defaultValue: true));
AddColumn("dbo.Person", "Name", c => c.String(nullable: false, defaultValue: "Mirza"));
Or to add default SQL value, use
AddColumn("dbo.Person", "CreatedDate",
c => c.String(nullable: false, defaultValueSql: "GETDATE()"));
However there's a downside of this approach in my opinion which is you have to keep a track of your (useless) migrations.
Just found this post looking for an answer to the same issue. Here's a work around that works for me.
Create a partial class for the entity (DB Table) you want to specify default values for, eg:
namespace myApplication.MyModel
{
public partial class myEntityName
{
public myEntityName(bool InitialiseOnConstruct) : this()
{
if (InitialiseOnConstruct)
{
this.property1 = defaultValue1;
this.property2 = defaultValue1;
}
}
}
}
Then in the code, to construct the entity:
thisEntity = new EntityName(true);
OK, it's an extra step, but it works. Hope that helps.

Is it possible to mix database first and code first models with entity framework?

I am about to begin a web application where I would like to use the Entity Framework with (mostly) code first models.
However, in addition to the application-specific models I plan to create, I have to use an external user database. Is it possible to specify one of my models as database first and to use a separate database context?
Technically, it's possible, but I wouldn't recommend it. It's far better to just use code-first across the board. Yes, ironically, you can use "code-first" with an existing database.
Just create POCOs that match the tables in your existing database. If your POCO is not named the same as your table (not all table names would be valid or appropriate class names), you can use the Table attribute to explicitly tell EF what table your POCO works with:
[Table("SomeTable")]
public class MyAwesomeEntity
{
...
}
Then, you'll need a separate context specifically for this existing database and any entities that belong to it. All you have to do is 1) tell it what connection string it should use and 2) turn off database initialization, so EF doesn't try to actually create the database.
public MyExistingDatabaseContext : DbContext
{
public MyExistingDatabaseContext()
: base("MyExistingDatabaseConnectionStringName")
{
Database.SetInitializer<MyExistingDatabaseContext>(null);
}
// DbSets here
}
And that's it. Whenever you need to work with an entity from this existing database, just new up this context or get it some other way, such as through a DI (dependency injection) container, and go to town.
You should use the code first from database option if you already have an existing database available but want to use code first.
1) In your Models folder, right click on Add, New item,
2) Select ADO.NET Entity Data Model in the Data tab.
3) Enter a model name,
4) Select Code First from database.
5) Select connection string,
6) Choose your database objects you want to include in your model.
You don't have to write the code for the context and model from scratch because it will generate the classes for you.

Entitiy Framework, use same model for two tables with same layout but different table names

I have two tables that have the same layout -
Report Table
ID
ReportCol1
ReportCol2
In another database I have
Reporting Table
ID
ReportCol1
ReportCol2
I want to use a single entity model called Report to load the data from both of these tables.
In my context class I have
public DbSet<Report> Report{ get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ReportMap());
}
In my call to the first database Report table I get the results as expected.
I change the connection string to point to the second database, but I can't change the name of the table in the table mapping.
I don't want to use stored procs for the reason outlined in my comment.
What can I do, short of the tables names in the database(that is not an option).
Have you tried this fluent API modelBuilder.Entity<Report>().ToTable("Reporting"); ? You may need to write this so it conditionally does this based on which database you are connecting to. You may need to have your configuration allow you to say "DatabaseA uses this mapping and connection string", and "DatabaseB uses this other mapping and conenctions string", and rather than changing the connection string, you specify which database by some name/key, and your app looks up that name to determine which mapping code to run.
if(dbMappingconfig == DbMapping.A)//some enum you create
{
modelBuilder.Entity<Report>().ToTable("Reporting");
}
If your goal is to be able to pass these entities to other methods like DisplayReport(Report r) so that you don't have to duplicate code, you could have both Reporting and Report classes implement a IReport interface.
EF also supports inheritance hierarchies, so you could have them inherit from the same class, BUT I havfe a strong feeling that will not work across databases.
If the OnModelCreating doesn't rerun, it's probably already cached. Put modelBuilder.CacheForContextType = false; in there so it doesn't cache it in future, and to clear the current cache I think you can just do a Clean+Rebuild. This will come at the price of rebuilding the model everytime instead of reusing a cache. What you'd really want is use the cache up until the connection string changes. I don't know of anyway to manually clear the cache, but there might be a way. You can manage the model building yourself:
DbModelBuilder builder = new DbModelBuilder();
// Setup configurations
DbModel model = builder.Build(connection);
DbCompiledModel compiledModel = model.Compile();
DbContext context = new DbContext(connection, compiledModel);
But that will introduce additional complexities since you will need to manage the caching yourself.
While searching on this, I came across this that looks like they are trying to accomplish the same thing, as well as having gone down the same page, see Final section in question: How to map an Entity framework model to a table name dynamically
Are you able to create the same named view in each database and map to that instead of a variable table name?
I have 2 copies of tables with different names in my solution and deal with that by having 2 contexts and 2 sets of map files (generated text templates)

Entity Framework (4.3) looking for singular name instead of plural (when entity name ends with "s")

Here's my situation:
I have been working on an ASP.NET MVC 3 application for a while. It has a database (built out of a db project; I'm going db-first) for which I have an edmx model and then a set of POCOs. My entities have plural names in the database and POCOs have singular names. Everything maps nicely without a problem.
Or used to until I added a new table (called TransactionStatuses). Now all of the old entities still work but the new one does not. When I try to eagerly load it together with a related entity:
var transactions = (from t in db.Transactions.Include(s => s.TransactionStatus) //TransactionStatus - navigation property in Transactions to TransactionStatuses
where t.CustomerID == CustomerID
select t).ToList();
I get
Invalid object name 'dbo.TransactionStatus'.
I even did a simpler test:
List<TransactionStatus> statuses = db.TransactionStatuses.ToList();
= same result.
I have updated (and even re-created) edmx from the db and have gone through it back and forth trying to figure out what is different about the mapping for dbo.TransactionStatus*es* which trips the whole thing up.
If somebody can point me in the direction of a fix it'd be wonderful.
P.S. Turning off pluralisation is not an option, thanks.
Update: I figured it out - my answer below.
This is probably happening because even though the intention was to use the Database First flow, in actual fact the application is using Code First to do the mapping. Let me explain a bit more because this can be confusing. :-)
When using Database First with the EF Designer and the DbContext templates in Visual Studio three very important things happen. First, the new Entity Data Model wizard adds a connection string to your app containing details of the Database First model (i.e. the EDMX) so that when the application is run it can find this model. The connection string will look something like this:
<connectionStrings>
<add name="MyEntities"
connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string="data source=.\sqlexpress;initial catalog=MyEntities;integrated security=True;multipleactiveresultsets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
Second, the generated context class makes a call to the base DbContext constructor specifying the name of this connection string:
public MyEntities()
: base("name=MyEntities")
{
}
This tells DbContext to find and use the "MyEntities" connection string in the config. Using "name=" means that DbContext will throw if it doesn't find the connection string--it won't just go ahead and create a connection by convention.
If you want to use Database First, then you must use a connection string like the one that is generated. Specifically, it must contain the model data (the csdl, msl, ssdl from the EDMX) and you must make sure that DbContext finds it. Be very careful when changing the call to the base constructor.
The third thing that happens is that OnModelCreating is overridden in the generated context and made to throw:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
This is done because OnModelCreating is only ever called when using Code First. This is because OnModelCreating is all about creating the model, but when you are using Database First the model already exists--there is nothing to create at runtime. So if OnModelCreating is called then it is probably because you started using Code First without meaning to, usually because of a change to the connection string or the call to the base constructor.
Now, it might be that you want to use Code First to map to an existing database. This is a great pattern and fully supported (see http://blogs.msdn.com/b/adonet/archive/2011/03/07/when-is-code-first-not-code-first.aspx) but you will need to make sure mappings are setup appropriately for this to work. If the mappings are not setup correctly then you will get exceptions like the one in this question.
Got it!
Horrible, horrible experience...
In short: EF cannot correctly pluralize entity names that end with "s" (e.g. "status", "campus", etc.)
Here's how I got it and proof.
I've created and re-created my original set up several times with the same result.
I also tried renaming my table to things like TransStatus and the like - no luck.
While I was researching about this I came across the pluralization article by Scott Hanselman where he added pluralization rules for words like sheep and goose. This got me thinking "what if he problem is in the actual name of the entity?"
I did some searching about the word status in particular and found this report of the problem on Connect. I rushed to try renaming my entity...
Renaming TransactionStatuses to TransactionStates (while even keeping the columns as StatusID) fixed the issue! I can now get List<TransactionState> statuses = db.TransactionStates.ToList();
I thought the problem was with the particular word status in the name... But after vocally complaining about this to a friend I was suggested that maybe the problem is with the word ending with "s"... So I decided to check it out.
I set up another table called Campuses and matching POCO Campus (and updated the edmx). Did the simple test List<Campus> test = db.Campuses.ToList(); and got the now expected
Invalid object name 'dbo.Campus'.
So there you go, the mighty EF cannot handle pluralization of words ending with "s". Hopefully, the next poor bugger hitting the problem will find this question and save him- or herself 3-4 hours of pain and frustration.
You mention EDMX but I can't tell if you are doing databse first with EDMX or code first and just using EDMX to see what's going on.
If you are using Code First, then you can use a configuration to specify the table name. Data Annotation is [Table("TransactionStatuses")], fluent is modelBuilder.Entity().ToTable("TransactionStatuses").
(I'm typing the annotation and fluent code from memory so double check references. ;) )
If you are using database first, the SSDL should absolutely be aware of the name of the database table, so I'm guessing that you are using code first & the edmx is just for exploration. (???)
hth
Sigh. Same type of an issue with the class and model Photo and Video; it is looking for the table Photoes and Videoes. I hate to just change the table name, but not much of a choice it looks like.

Categories