Can't access database when I change asp.net mvc model properties - c#

I'm developing a project and I made changes to my models, and now whenever I run my project I get these errors for all the model that I made changes to:
for my person model:
Invalid column name 'Location'.
Invalid column name 'EmailAddress'.
Invalid column name 'PlaceOfBirth'.
for my guardian model:
Invalid object name 'Admission.Guardian'.
Here is my DbContext model:
public class SchoolInfoEntities: DbContext
{
public DbSet<Students> Student { get; set; }
public DbSet<Class> Classes { get; set; }
public DbSet<Guardian> Guardians { get; set; }
public DbSet<Staff> Staffs { get; set; }
public DbSet<Subject> Subjects { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<SchoolDetails> SchoolDetails { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Students>()
.HasMany(t => t.Guardians)
.WithMany(t => t.Students)
.Map(m =>
{
m.ToTable("Admission.StudentGuardian");
m.MapLeftKey("StudentId");
m.MapRightKey("GuardianId");
});
modelBuilder.Entity<Staff>()
.HasMany(t => t.Subjects)
.WithMany(t => t.Staffs)
.Map(m =>
{
m.ToTable("Admission.SubjectInstructor");
m.MapLeftKey("StaffId");
m.MapRightKey("SubjectName");
});
modelBuilder.Entity<Staff>()
.HasMany(t => t.Departments)
.WithMany(t => t.Staffs)
.Map(m =>
{
m.ToTable("Admission.StaffDepartment");
m.MapLeftKey("StaffId");
m.MapRightKey("DepartmentId");
});
Database.SetInitializer<SchoolInfoEntities>(null);
}
}
Is there anything that I'm not considering? Please help me guys.

You can't change the model fields without updating the related database fields. You need to create a migration and apply it in order to keep your models in sync with the database schema.
https://docs.asp.net/en/latest/data/ef-mvc/migrations.html
If you have a production version of the database you'll need to run the same migrations on it.

You need to run below commands on the Package Manger console before run your app.
Note : you need to set correct connection string where the place (db server) you need to run the scripts.
PM> Add-Migration "Added_New_Properties"
PM> Update-Database

Since you are using Code First, EntityFramework always make sure that the model is synchronized with the database, when the application starts, it compares the classes and its properties with the tables and columns in the database taking into consideration any changes you made using the Fluent API inside your Context.
When you add a new property into any class, you have to either add a corresponding column in the database table that maps to this class, or you can let EntityFramework do it for you by using Migration.
You have to enbale migration first using the Enable-Migrations command
After that, run the command Add-Migration [Migration Name] which will compare the model to the database and generate some code inside the Migrations folder to update the database, it should have an Up and Down methods.
To run the Up method which updates the database to the code, you have to run the Update-Database command.
All of these commands must run inside the Package Manager Console which you can reach from Tools -> NuGet Package Manager -> Package Manager Console.

Related

How to map new class to an existing table using c# Fluent API?

In my application, there is a many-to-many relationship between two entities (ChartOfAccount & GL). Once I create the relationship a new table got created (ChartOfAccountGLs). Now I tried to create a new class to map those two entities with one-to-many relationship (ChartOfAccountGL-->ChartOfAccount & ChartOfAccounGL-->GL). But when I tried to update, database package manager console gave this error
"There is already an object named 'FK_dbo.ChartOfAccountGLs_dbo.ChartOfAccounts_ChartOfAccountId' in the
database. Could not create constraint or index. See previous errors."
Below shows my ChartOfAccountGL class:
[Table("ChartOfAccountGLs")]
public class ChartOfAccountGL
{
public int ChartOfAccountId { get; set; }
public int GLId { get; set; }
public ChartOfAccount ChartOfAccount { get; set; }
public GL GL { get; set; }
}
ChartOfAccountGLConfiguration :
public class ChartOfAccountGLConfiguration : EntityTypeConfiguration<ChartOfAccountGL>
{
public ChartOfAccountGLConfiguration()
{
//Define two composite keys
HasKey(k => new { k.ChartOfAccountId, k.GLId });
Property(a => a.ChartOfAccountId)
.HasColumnName("ChartOfAccountId");
Property(b => b.GLId)
.HasColumnName("GLId");
//Mapping classes
HasRequired(a => a.ChartOfAccount)
.WithMany(b => b.ChartOfAccountGL);
HasRequired(f => f.GL)
.WithMany(b => b.ChartOfAccountGL);
}
}
Does anyone has an idea where have I done the mistake??
It's a known problem for when you upgrade the model. In EF6 you can use ignore changes but in ef core, check this:
https://github.com/dotnet/efcore/issues/4237
There is no equivalent for IgnoreChanges when generating migrations right now. Not on powershell, or using ef migrations add. This needs to come to EF7 and is a fundamental part of the migration work, specially for apps that are working with existing tables.
If you are using ef core, try this (from a comment in the issue):
This is probably just stating the obvious... but as a workaround for the moment you can generate a migration and then delete the code from the Up/Down methods.

Entity Framework added extra `s` to table name in runtime query if add `PluralizingTableNameConvention` to avoid extra `s` it throw error

I have simple context with 3 tables.
database tables are already present but using code first approach.
Model Device.cs is -
public class Device
{
public System.Guid Id { get; set; }
public string Name{ get; set; }
}
public class sampledbContext : DbContext
{
public sampledbContext ()
: base("name=sampledbContext ")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public virtual DbSet<Device> Devices { get; set; }
}
To avoid extra s I have added above line into OnModelCreating but it is giving an error -
System.InvalidOperationException: 'The model backing the 'sampledbContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).'
Database was already created and I try to use code first approach here.
I have not done update-database yet.
I tried doing Enable-Migration and Update-database it creates table with name s like Devices why ? s is added ?
You've turned off auto-migrations in the line:
Database.SetInitializer<IoTSimulatordbContext>(null);
And therefore you will need to run update-database manually to update the model (you can run this via package manager console). If you have any data in your tables it is likely that the migration will fail due to the possibility of losing data, in that case you will need to either delete all data from the tables first or make a custom migration script to handle copying the data first. As this seems like a test it may be better to restart the migration project with the pluralisation off from the beginning.
You can add a DataAnnotation to describe the Schema and Table name to your Table class such as this;
[Table("Device", Schema = "MySchema")]
This will give you more control over the naming.

Repeated Update causes tracking error

Im using VisualStudio 2017 with .Net Core 2 and EntityFrameworkCore (v2.0.1). The application is a console application which starts an MQTT Client and then processes the received messages, storing them into a database.
Each time the application starts and on the first update it works as expected. However on each subsequent update with the same data (none, one or more fields are changed), it throws an System.InvalidOperationException with the following message:
The instance of entity type 'Entity1' cannot be tracked because
another instance with the key value '[SomeKeyValue]' is already being
tracked. When attaching existing entities, ensure that only one entity
instance with a given key value is attached.
The entities are fairly simple, only using a One-To-Many relationship.
I also have the same repository used in a WebApi writing to the same database, and here the same update code works as expected without errors. I hooked up the Console App to use the WebApi instead, and this works, even though it is exactly the same Repository and Database.
I tried various recommendations I found on the internet, which is for example to explicitly detach the entity, but none of that worked.
The setup is the same as for the Asp.Net WebApi, using dependency injection
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));
The One-To-Many Relations is configured like this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity1>()
.HasOne<Entity2>(di => di.Entity1)
.WithMany(d => d.Entity2)
.HasForeignKey(d => d.Entity1Id);
}
The Entities are:
public class Entity1: ClientChangeTracker
{
[Key]
public string Id{ get; set; }
public ICollection<Entity2> Entity2{ get; set; }
...
}
public class Entity2: ClientChangeTracker
{
[Key]
public string Id{ get; set; }
public Entity1 Entity1{get; set; }
public string Entity1Id{ get; set; }
...
}
The repository code for adding entity:
public void AddEntity(Entity1 entity1)
{
if (_context.Entity1s.Any(x => x.Id== entity1.Id))
{
_context.Entity1s.Update(entity1).Entity;
}
else
{
_context.Entity1s.Add(entity1).Entity;
}
_context.SaveChanges();
}
Anybody any idea why this is happening and how it can be fixed?
It appears that configuring DbContext in the IoC container requires an extra step inside of a Console Application. Instead of
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));
it requires an addition parameter to specify the ServiceLifetime as Transient:
services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString), ServiceLifetime.Transient);
This seems to fix the problem.

How to create all tables on database when application is loading?

I'm learning about Entity Framework and I want to create a project with it. I've use FluentNhibernate in my project but now I want to try Entity, but I have a doubt about how to create all tables(DBSet) when the application is loading. In my case I have 3 tables: Cliente, Produto, Venda, that I want to create when application is loading but I don't know how to do this.
How could I do this ?
trying
[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
public class DatabaseContext : DbContext{
public DatabaseContext():base("default"){
Database.SetInitializer<DatabaseContext>(new CreateDatabaseIfNotExists<DatabaseContext>());
//Database.CreateIfNotExists();
}
public DbSet<Cliente> clientes { get; set; }
public DbSet<Produto> produtos { get; set; }
public DbSet<Venda> vendas { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder){
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Produto>()
.Property(p => p.valor)
.HasPrecision(9,2); // or whatever your schema specifies
Database.SetInitializer<DatabaseContext>(null);
base.OnModelCreating(modelBuilder);
}
}
Assuming you already have all your DbContext and Entities setup and you are just asking about generating/updating the database, you are looking for Entity Framework's migration features.
Open Package Manager Console and run the following commands in your project:
// Enable migrations to your project
Enable-Migrations
// Add migrations to your project
Add-Migration
// Update any changes to the generated database
Update-Database
More details here:
https://martinnormark.com/entity-framework-migrations-cheat-sheet/
In the OnModelCreating method remove:
Database.SetInitializer<DatabaseContext>(null);
i suggest you to read:
http://www.entityframeworktutorial.net/code-first/database-initialization-strategy-in-code-first.aspx
and about automatic migration:
http://www.entityframeworktutorial.net/code-first/automated-migration-in-code-first.aspx

EF needs Update DB every time I debug my project

I use EF6 and MVC5
I use code-first for my project. and this is my DbContext:
public class ProjectServiceDBContext:DbContext
{
public ProjectServiceIranDBContext()
: base("ProjectServiceDBContext")
{ }
public DbSet<Service> Services { get; set; }
public DbSet<FormPost> FormPosts { get; set; }
public DbSet<Factory> Factories { get; set; }
public DbSet<PictureGallery> PictureGallery { get; set; }
public DbSet<Blog> Blog { get; set; }
public DbSet<Comment> Comment { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ServiceMapping());
modelBuilder.Configurations.Add(new FactoryMapping());
modelBuilder.Configurations.Add(new FormPostMapping());
modelBuilder.Configurations.Add(new PictureGalleryMapping());
modelBuilder.Configurations.Add(new BlogMapping());
modelBuilder.Configurations.Add(new CommentMapping());
modelBuilder.Configurations.Add(new UserMapping());
}
}
everything was fine before I Added new field to my Blog Model.
I use migrations to update my database . but its works just for one debug , if I stop debugging and start debugging again I get this error for updating database:
The model backing the 'ProjectServiceDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database (http://go.microsoft.com/fwlink/?LinkId=238269).
I should use add-migration and update-database every time before debugging
what should I do?
I also delete Migration folder in my solution , and delete my tables in Database and try again and it's not works. also I create new DbContext but still this error is exist.
Try putting this in the constructor for your DbContext:
Database.SetInitializer<ProjectServiceDBContext>(null);
By default, Entity Framework Code-First uses the CreateDatabaseIfNotExists initializer. I think that's what is causing your problem..
If you change you code-first db models, the database needs to be updated to reflect that change. That is when you need to add a new migration and then apply it to ALL databases the application uses.
To apply to a production db, you might want to generate an SQL script of the changes using update-database -script.
Doesn't answer why your context is continually out of date but you could consider using AutomaticMigrations whilst in development.
See section Enabling Migrations

Categories

Resources