I have an EF Core 6 context that uses temporal tables, and am trying to rename one of the properties on a model.
I have a model that was named PropertyGroupsInvestors, which I renamed to Investment. That worked fine.
I then noticed that the InvestorPayment model had the following...
public int PropertyGroupsInvestorsID { get; set; }
public PropertyGroupsInvestors PropertyGroupsInvestors { get; set; } = new();
...which should also have been renamed. I renamed the two properties as follows...
public int InvestmentsID { get; set; }
public Investment Investment { get; set; } = new();
...and added a migration.
However, when I tried to update the database, it failed with the error "Setting SYSTEM_VERSIONING to ON failed because table 'MyProject.dbo.InvestorPayments' has 10 columns and table 'MyProject.dbo.InvestorPaymentsHistory' has 9 columns."
Looking in SQL Server Management Studio, I can see that both the InvestorPayments and corresponding history tables have both the old PropertyGroupsInvestorsID column and the new InvestmentId column. They both have 10 columns, so I'm not sure what he message means though. See the screenshot...
Any idea how I fix this? Ideally I need to get rid of the PropertyGroupsInvestorsID column from both tables.
Thanks
There is a problem with the renaming of columns in the system versioning table using a code-first approach. So a quick solution (if you don't want to drop temporal tables) can be just to create two migrations. One migration to add a new column, and the second migration to remove the old column.
So first migration will contain both, PropertyGroupsInvestorsID and InvestorsID and then remove PropertyGroupsInvestorsID to create a new migration.
The same problem here like deleting or modifying one field, it looks like when you have a system-versioned table, you can't modify the structure because it's linked to the history table.
Using SQL server doesn't look like there is any problem:
https://learn.microsoft.com/en-us/sql/relational-databases/tables/add-columns-to-a-table-database-engine?view=sql-server-ver15
Related
I am developing an ASP.NET Core 5 application and I just made a modification to one of the model classes as follows
...
public long OfferId { get; set; }
[ForeignKey("OfferId")]
public RequestOffer Offer { get; set; }
...
This requires that I add migration and update database.
However, when I try to run update-database I get the following error
Column names in each table must be unique. Column name 'Discriminator' in table 'AspNetUserTokens' is specified more than once
I have tried to run the migration with the -ignoreChanges flag as I saw in a solution proposed on a similar StackOverflow question but it did not make a difference.
My worry is that I never made any changes to that table (AspNetUserTokens) in this update. However, I realize that in the migration file, I see that all the codes for the previous migrations are repeated as if I am rerunning the migrations afresh which I am not doing.
So, it looks like all the database tables are being recreated. I was expecting the migration file to contain code for only the changes I just made but it rather contains all the changes in the previous migrations as well starting from the very first migration I ran.
I will appreciate any guide to help me resolve this so I can update my database and continue with the project.
Thank you
I am using SQLite-net together with the TwinCoders NuGet for extension methods in a MvvmCross Xamarin project. I want to make the database to stay updated even if I will modify the models in future.
My question is: If I use the CreateTable function for creating a SQLite table based on the model and the database already exists on the tablet/phone, but it has a different structure (let's say that the table has a missing column which was added in the last update), will this function alter the existing table? Thanks!
Thanks for your answers! SQLite-Net implements automatic migrations indeed. It treats the lack of "ALTER DROP COLUMN" and "ALTER RENAME COLUMN" commands from SQLite as follows:
if the name of one column is changed, then a new column will be created with the new name and the old one will be ignored by the queries
if the column is dropped, then it will remain in the database, but the queries will ignore it
I didn't try yet what happens when I change the datatype of one column (attribute), but I hope it will not be the case in our project.
For me the answer has always been yes. I changed the name of one of the properties in my model and that ended up leaving the data in place and each existing record had that new property but it was empty.
So it went something like this:
Original:
class Model {
int Id { get; set; }
string Date { get; set; }
}
Changed:
class Model {
int Id { get; set; }
string Dates { get; set; }
}
Now all of the records still had Id values and were not erased but they all also had empty Dates columns, as would be expected.
Needless to say, a new table was not created.
Edit: Also note that I am using SQLite-Net only, no extension libraries or anything but the end result should be the same.
So I made a little relational database with about seven tables, and I'm using some of these to make a form. So I made an ADO.NET Entity Data Model to diagram the forms and generate classes based on the tables. Now I want to give the class properties DisplayNames (using System.ComponentModel). The forms also get pretty big, and there's a lot of DisplayNames.
public partial class ParticularForm
{
public System.Guid ParticularForm1 { get; set; }
public System.Guid GeneralFormFieldsID { get; set; }
#region Particular Form
[DisplayName("What's your name?")]
public string Name { get; set; }
[DisplayName("How many friends do you have?")]
public Nullable<byte> FriendsAmount { get; set; }
// (etc...)
Ack! So it looks like the ADO.NET Entity Data Model gave one of the columns an incorrect name: "ParticularForm1" should be called "ParticularFormID". So I go into the database, rename the "ParticularForm" column to "ParticularFormID". Now I want to update references to ParticularForm1 in the scaffolded Form.tt classes, changing the name to name ParticularFormID. So here's what I do:
I go into the Form.edmx diagram and click Update Model from Database. It doesn't allow me to refresh a single table, it refreshes all of them at once. Afterwards I save, and now the .edmx model correctly shows the "ParticularFormID" column. But it still shows the weird "ParticularForm1" column, and in addition to this, I've lost like 100 display names.
So I undo the pending changes in TFS and I take a new approach.
public partial class ParticularForm
{
public System.Guid ParticularFormID { get; set; }
I went back into Form.tt > ParticularForm.cs and change the property's name from ParticularForm1 to ParticularFormID. Then I go back to the Designer and save the changes. I get the message:
This file has been modified outside of the source editor. Do you want to reload it?
Sure. Then I get it again for every table in addition to the only one I changed. Every time I click No, no changes are made, but TFS still says there are pending changes. When I click Yes for ParticularForm.cs, all of its DisplayNames are removed again, and the .cs file reverts back to the prior naming conventions that ADO.NET chose, and undoes my change.
I'd like to keep the work I've already done with respect to the DisplayNames, but change a single column name without losing all of my work. Any ideas on what is going on? Why don't ADO.NET Entity Data Models respect me?
The answer turned out to be that one should hold the data annotations in a MetadataType class. Not just [DisplayName()], like, everything.
Part of my issue was that I wasn't reading this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// **Manual changes to this file will be overwritten if the code is regenerated.**
// </auto-generated>
//------------------------------------------------------------------------------
I've been banging my head all day long. I'm new to MVC 5 (MVC and ASP.NET in general) and I can't figure out how do I add an extra table to my current Database (created using CodeFirst approach), and read its content.
Heck, I don't know how to read the other columns I have in the AspNetUsers Table from Identity.
Would someone kindly tell me how this is done? Thanks a million
Edit:
Ok. So I have been tirelessly looking for a solution, and I've come across 35% of it.
I've stumbled upon a book called "Getting Started with Entity Framework 6 Code First using MVC 5 with Tom Dykstra"
Now I know that for creating a table you just create a class under the Model folders, and use a DbSet<> command where you had applied the DbContext call.
Now, what's the problem here? I started from a blank template, since that is the suggestion from "Pro ASP.NET MVC 5" from Adamn Freeman, and I don't want Google, Facebook Authentication.
I have been able to populate the defacto AspNetUsers table with custom fields, and insert Data into it.
What I want to with it, is to create a relational table with a foreign key which should reside in the defacto AspNetUsers table, and I don't how to do it.
Create the entity class (new table). You must specify an attribute as the primary key that should be named (CLASSNAME)ID Ex:
public class Product
{
public int ProductID { get; set; }
public string PropriedadeTeste { get; set; }
}
Map this entity in your implementation of DbContext. This means that Products table will contain Product objects:
public class EFDbContext : DbContext
{
public EFDbContext() : base("DatabaseName") { }
public DbSet<Product> Products { get; set; }
}
Enable migrations in your project (in the Package Manager Console)
Enable-Migrations -ProjectName SportStore.Domain -ContextTypeName ENTER_NAMESPACE_HERE.EFDbContext
Generate the migration - in this example, it will be generated a file named something like 201409172255007_Product.cs, in the Migrations folder:
Add-Migration -ProjectName PROJECT_NAME Product
Update the database:
Update-Database -ProjectName PROJECT_NAME -TargetMigration Product
I am trying to create database using Code First approach. When I run the following code I am getting the following exception. Is there anything wrong in the fields that I defined? How can we overcome this?
Exception:
An error occurred while updating the entries. See the inner exception for details.
Inner Exception:
"Invalid object name 'dbo.Dinners'.
Note: I do not have such a table (Dinners) in the database. The code is supposed to create the tables. I just gave connection string to identify the server as mentioned in EF Code First: Cannot connect to SQL Server. Should I change the connection string?
Connections String:
string connectionstring = "Data Source=.;Initial Catalog=LibraryReservationSystem;Integrated Security=True;Connect Timeout=30";
The LibraryReservationSystem database is already existing database. It has no tables. I am expecting EF to create the tables.
The connection string I copied from a working LINQ 2 SQL application. Do I need to make any changes to it to supply to EF?
UPDATE
When I included the following code, the exception got changed. Now it says - "Invalid object name 'dbo.Dinner'.". It is now complaining about Dinner table; not Dinners table.
protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
Original CODE
static void Main(string[] args)
{
string connectionstring = "Data Source=.;Initial Catalog=LibraryReservationSystem;Integrated Security=True;Connect Timeout=30";
using (var db = new NerdDinners(connectionstring))
{
var product = new Dinner { DinnerID = 1, Title = 101 };
db.Dinners.Add(product);
int recordsAffected = db.SaveChanges();
}
}
using System.Data.Entity;
namespace LijosEF
{
public class Dinner
{
public int DinnerID { get; set; }
public int Title { get; set; }
}
public class RSVP
{
public int RSVPID { get; set; }
public int DinnerID { get; set; }
public virtual Dinner Dinner { get; set; }
}
//System.Data.Entity.DbContext is from EntityFramework.dll
public class NerdDinners : System.Data.Entity.DbContext
{
public NerdDinners(string connString): base(connString)
{
}
public DbSet<Dinner> Dinners { get; set; }
public DbSet<RSVP> RSVPs { get; set; }
}
}
REFERENCE
http://nerddinner.codeplex.com/discussions/358197
Entity framework - Invalid Object Name
Invalid object name 'dbo.TableName' when retrieving data from generated table
http://blogs.msdn.com/b/adonet/archive/2011/09/28/ef-4-2-code-first-walkthrough.aspx
The LibraryReservationSystem database is already existing database. It
has no tables. I am expecting EF to create the tables.
That's not correct. If the database exists EF doesn't create any tables in this database. EF can create the database if it doesn't exist. That is the default database initializer CreateDatabaseIfNotExists that gets applied if you don't change it explicitly. You can select two other initializers: DropCreateDatabaseAlways or DropCreateDatabaseIfModelChanges. But neither of those will only create tables in an existing database but instead delete the database completely and create it from scratch including all tables.
What can you do:
Either delete the database manually (in SSMS for example), then EF will create a new one including the tables
Or use the DropCreateDatabaseAlways initializer once to let EF create the database including the tables, then remove the initializer again
Or if you can't delete the database for whatever reason write SQL code in the Seed method that adds the tables to the database (Wrong, thanks to Mark Stafford's comment)
Or use Code-First Migrations (EF >= 4.3) to add new tables to an existing database when you have added new entities.
#Slauma's answer is the right one - the tables are created upon initialization. It's probably easiest to just delete the database and let EF create it (if you leave your connection string as is, it will create a database called LibraryReservationSystem on the local machine; you should probably specify an explicit host name if you're going to use the connection string in the config at this point).
You would need something along the lines of:
public class NerdDinnersInitializer : DropCreateDatabaseIfModelChanges<NerdDinners> { }
And you would also need to set the initializer in your Main method:
Database.SetInitializer(new NerdDinnersInitializer());
Word to the wise: NEVER deploy an application with an initializer like the one above. You can see this blog post about how to control initializers via the config file for more details on how to control this in production applications.
I've just ran into the exact same issue - I'd already created my database on a development SQL box inside our network that needs SQL authentication.
When I ran my app, no tables were created. I found this awesome but simple article about creating a Code First Database Initializer Strategy which first checks to see if the database exists and then runs a script against the database to create the tables.
As stated in the article - pay attention that when such a strategy is deployed, whenever the application starts over, all the database tables will be recreated! This strategy should only run once.
But you already knew that.
As the error suggests, you do not have a table called Dinners within your database.
Are you using Single or Plural table names? i.e. Dinner or Dinners?
As I understood, you are expecting the code to create DB automatically based on your entities description. But this will not happen unless you create DB explicitly. Please check the following link http://www.simple-talk.com/dotnet/.net-framework/entity-framework-4460---learn-to-create-databases-from-the-model/
and this tutorial on EF codefirst: http://codefirst.codeplex.com/
Once you have your entities designed you can right-click the workspace of the EDMX file and select 'Generate Database from Model...'. Click through until you have a script in your window. For that script you will have to remove DB creation step (if it is there) and go straight for CREATE TABLE ...
Copy-Paste and execute in whatever DB you've got. You might have to adjust the script for a specific RDBMS.