Entity Framework Code First Initial Create - entity-framework

I first time trying to create web app (.net core 2.1) from scratch with Entity Framework. For some reason I can't get DB generated.
So I installed EF nuget. And did next things:
Added class that inheres from DbContext:
public class ApplicationDbContext:DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Server> Servers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Server>().HasData(
new Server
{
Name = "My Server",
InUse = false
}
);
}
}
And created Entity:
public class Server
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public bool InUse { get; set; }
}
In startup.cs in ConfigureServices method I added:
var connectionString = Configuration.GetConnectionString("ApplicationConnection");
services.AddDbContext<ApplicationDbContext>
(options => options.UseSqlServer(connectionString));
Connection string coming from appsettings and I debugged it so it does coming through, and it same string that I using in other projects with just different Database name value and it should be ok.
Also I run from console Add-Migration command so I got Migrations folder with InitialCreate migration and some snapshot file.
But when I run app I don't get any error but it never hit break point inside InitialCreate.cs migration and so never create DB.
Any ideas where and what should I call to trigger those?

If you want entity framework automatically creates your database
In Configuration file, add this line in constructor:
AutomaticMigrationsEnabled = true;
Then add the code into DBContext:
Database.SetInitializer(new
DropCreateDatabaseAlways<YourDbContext>());
Then when the application already ran:
Database.SetInitializer(new
DropCreateDatabaseIfModelChanges<YourDbContext>());
You can also have a look MigrateDatabaseToLatestVersion
If you manually track version of database:
Update AutomaticMigrationsEnabled = false;
From console, run command Update-Database to migrate your database
manually

So I been able to create DB by adding next code inside Startup.cs in Configure() method
using (var scope = app.ApplicationServices.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
dbContext.Database.Migrate();
if (!dbContext.Servers.Any())
{
dbContext.Servers.Add(new Server
{
Name = "My Server",
InUse = false
});
dbContext.SaveChanges();
}
}

Related

EF Core migration

I have a working web application (an end point) containing a few methods and connected to two tables in sql server. This application is fully implemented from scratch by myself in an ashx file and does not follow any new or old architecture, simply some methods in ashx file that are remotely called and handle requirements of client. There are shared DLLs among client and server for data handling.
For some reasons I want to upgrade client side to Dot Net core, consequently common DLL needs to be upgraded and finally the end point.
Now I'm facing the problem that EF Core only supports code first, but there are ways for scaffolding . I started with Microsoft tutorials. Then I see There are certain ways for migrating and scaffolding existing database, but I got stuck for hours in first step of using command "dotnet ef dbcontext scaffold "Data Source=..." . Then usually tutorial materials get combined with other technologies like asp.net core very fast, I need to read tons of technologies to do a simple task.
I'm worried I'm going the wrong way. there are only two tables and I can implement table structure by hand. Isn't there any sample code that I can modify it's table definitions and I can restart my project soon? If things are so hard, I will omit EF from my project and redefine the whole end point logic by text sql queries.
I can implement table structure by hand.
Great. Simply create a DbContext subtype that has a DbSet for each of your entities. The only thing scaffolding does is save you time.
Here's a complete example for SQL Server:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Order> Orders { get; } = new HashSet<Order>();
}
public class Order
{
public int CustomerId { get; set; }
public int Id { get; set; }
public Customer Customer { get; set; }
}
public class Db : DbContext
{
string connectionString = "Server=localhost; database=efcore5test; integrated security = true;TrustServerCertificate=true;";
public DbSet<Customer> Customers { get; set; }
public DbSet<Order> Orders{ get; set; }
public Db(string connectionString) : base()
{
this.connectionString = connectionString;
}
public Db() : base()
{
this.Database.SetCommandTimeout(180);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var constr = this.connectionString;
optionsBuilder.LogTo(Console.WriteLine);
optionsBuilder.UseSqlServer(constr, o => o.UseRelationalNulls().CommandTimeout(180).UseNetTopologySuite());
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>().HasKey(o => new { o.CustomerId, o.Id });
base.OnModelCreating(modelBuilder);
}
}

Why table not exists while I create a in-memory sqlite database with entityframework core?

I want to create an in-memory SQLite database.
Here is startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<TestDBContext>().AddEntityFrameworkSqlite();
}
Here is the Model of database:
public class TestModel
{
public string UserName { get; set; }
[Key]
public string id { get; set; }
}
Here is the DBContext of database:
public class TestDBContext : DbContext
{
public virtual DbSet<TestModel> Test { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=:memory:");
}
}
And here is the controller:
private readonly TestDBContext TestDBContext;
public HomeController(ILogger<HomeController> logger,TestDBContext _TestDBContext)
{
_logger = logger;
this.TestDBContext = _TestDBContext;
}
public IActionResult Index()
{
TestDBContext.Database.EnsureCreated();
TestDBContext.SaveChanges();
TestDBContext.Test.Add(new TestModel() { User = DateTime.Now.ToString(),id=Guid.NewGuid().ToString() });
TestDBContext.SaveChanges();
return View(TestDBContext.Test.ToList());
}
Every time it runs, it will report an error:
Inner Exception 1:
SqliteException: SQLite Error 1: 'no such table: Test'.
I have used the EnsureCreated and the EnsureCreated runs without any error. Why it still be like this?
EF Core's DbContext always opens and closes connections to the database automatically, unless you pass an already open connection. And when the connection gets closed, the Sqlite In-memory database will be removed. So I modified your code a little bit like this.
public void ConfigureServices(IServiceCollection services)
{
var connection = new SqliteConnection("datasource=:memory:");
connection.Open();
services.AddControllersWithViews();
services.AddDbContext<TestDBContext>(options =>
{
options.UseSqlite(connection);
});
}
And the Database Context class - I added the constructors so that I can provide the parameters.
public class TestDBContext : DbContext
{
public TestDBContext(DbContextOptions options) : base(options)
{
}
protected TestDBContext()
{
}
public virtual DbSet<TestModel> Test { get; set; }
}
And instead of creating the database in the Index action method, create it in the startup.
Also, opt to use the DbContext.Database.Migrate() method instead of EnsureCreated else you won't be able to use migrations later down the line.

Database changes are not vsiisble after executing migrate.exe

I am using entity framework 6.1. I used code-based migration i.e. Migrate.exe to update my database (Add a new property to table). Migrate.exe executed fine and I did refresh on my SQL Server database but the newly added column was not visible.
I inserted a row into the table and checked table and found that now newly column is added to the table.
I would like to know why this newly created column not visible immediately after executing migrate.exe and why I have to hit database to see my update model changes?
Please respond.
I have used below database context and initializer.
public class AMLDBContext : DbContext
{
public DbSet<Template> Templates { get; set; }
public DbSet<Property> Properties { get; set; }
public AMLDBContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<AMLDBContext, Migrations.Configuration>());
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Property>().HasKey(s => new { s.PropertyName, s.TemplateId });
modelBuilder.Entity<ReturnAttribute>().HasKey(s => new { s.AttributeName, s.TemplateId });
base.OnModelCreating(modelBuilder);
}
}
I used below command for migrate.exe.
migrate.exe AutoDbUpgrade.exe /StartUpDirectory:"C:\TestProject\AutoDbUpgrade\AutoDbUpgrade\bin\Debug" /startupConfigurationFile=”AutoDbUpgrade.exe.config” /verbose

There is already an object named 'cars' in the database-data

I am developing an MVC project using code first. I create my database using code first as you can see here :
public class DataContext:DbContext
{
public DataContext()
: base("DefaultConnection")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<DataContext, MigrationsConfiguration>()
);
}
public DbSet<Member> Members { get; set; }
public DbSet<Traffic> Traffics { get; set; }
public DbSet<Car> Cars { get; set; }
public DbSet<Validation> Validations { get; set; }
public DbSet<Log> Logs { get; set; }
public DbSet<File> Files { get; set; }
}
I uploaded my project in the company server, and they used my project and entered some values to database, so after sometimes I changed some columns in database, and I added normally in SQL design to database table, so I changed some part of my code too, and now then I upload my published file I get this error :
There is already an object named 'Cars' in the database.
Note: I can't delete the database because I have data in it ,as i said I added the new columns to database, but my application can't connect to that database .
Migration part:
public class MigrationsConfiguration : DbMigrationsConfiguration<DataContext>
{
public MigrationsConfiguration()
{
this.AutomaticMigrationDataLossAllowed = true;
this.AutomaticMigrationsEnabled = true;
}
}
As you've got data in your production database already, don't use automatic migrations. Your first priority is to get your databases in sync with your model. How you do this will depend on how complicated your model is, e.g. how many tables. My suggestion would be:
Disable Automatic migrations
Point your dev copy at a blank database, and create an initial migration
Run Update-Database -Script to generate an SQL script for the migration
Alter the script by hand so that it can be run on your production database
Run this on your production database
Once you've got to this point, make sure you add migrations each time you want to make changes to your model, rather than making them by hand.

Can't Get EF 6 Code First To Create the Tables

I already have a database with tables outside EF scope. But I want that the tables which will be used by EF to be created automatically.
public class SessionInfo
{
public Guid Id {get;set;}
public string Name { get; set; }
public DateTime StartsOn { get; set; }
public DateTime EndsOn { get; set; }
public string Notes { get; set; }
}
public class StudentsDbContext:DbContext
{
public StudentsDbContext():base("name=memory")
{
Database.Log = s => this.LogDebug(s);
}
public DbSet<SessionInfo> Sessions { get; set; }
}
This code just throws an exception because the table SessionInfoes doesn't exist.
using (var db = new StudentsDbContext())
{
db.Sessions.Add(new SessionInfo() {Id = Guid.NewGuid(), Name = "bla"});
var st = db.Sessions.FirstOrDefault();
}
What do I need to do so that EF will create the "SessionInfoes" (whatever name, it's not important) table by itself? I was under the impression that Ef will create the tables when the context is first used for a change or a query.
Update
After some digging, it seems that EF and Sqlite don't play very nice together i.e at most you can use EF to do queries but that's it. No table creation, no adding entities.
EF needs additional information in order to do this. You'll have to specify an IDatabaseInitializer first. Take a look at this list and find one that is appropriate for your needs (for example: MigrateDatabaseToLatestVersion, DropCreateDatabaseAlways, DropCreateDatabaseIfModelChanges, etc).
Then create your class:
public class MyDatabaseInitializer : MigrateDatabaseToLatestVersion
<MyDbContext,
MyDatabaseMigrationConfiguration>
Then also create the configuration for the initializer (ugh right?):
public class DatabaseMigrationsConfiguration
: DbMigrationsConfiguration<MyDbContext>
{
public DatabaseMigrationsConfiguration()
{
this.AutomaticMigrationDataLossAllowed = true;
this.AutomaticMigrationsEnabled = true;
}
protected override void Seed(MyDbContext context)
{
// Need data automagically added/update to the DB
// during initialization?
base.Seed(context);
}
}
Then one way to initialize the database is:
var myContext = new MyDbContext(/*connectionString*/);
Database.SetInitializer<MyDbContext>(new MyDatabaseInitializer());
myContext.Database.Initialize(true);
Some people prefer the to use the command line to migrate databases, but I don't want to assume I'll always have access to the database from a command lin.