I try to run a CodeFirst example for Entity Framwork with SQLite.
The NuGet Package SQLite.CodeFirst is installed and runs without errors
but it doesn´t create a SQLite DB.
This is my code:
using SQLite.CodeFirst;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Text;
namespace EF6SqliteExample
{
class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var model = modelBuilder.Build(Database.Connection);
ISqlGenerator sqlGenerator = new SqliteSqlGenerator();
string sql = sqlGenerator.Generate(model.StoreModel);
}
public DbSet<Person> Persons { get; set; }
}
class Program
{
static void Main(string[] args)
{
using (var db = new MyContext())
{
var person = new Person() { Name = "John" };
db.Persons.Add(person);
db.SaveChanges();
}
}
}
}
The Connection-String is:
<connectionStrings>
<add name="MyDB" connectionString="data source=.\MyDB.sqlite" providerName="System.Data.SQLite" />
</connectionStrings>
The DbContext class has a method called .Migrate() which will go through the migrations pipeline and create your database if it does not already exist.
Here's a source: Entity Framework Migrations
What I pointed out in your code is, constructor of class MyContext is missing in your code. Add contructor with base and try again.
public MyContext() : base("MyDB")
{
}
after adding constructor in your class, if the Migrations folder is not available yet in your project, you have to write some command as below:
In your visual studio, go to view -> other windows -> package manager console
To enable migration, run enable-migrations . After executing it, you will find Migrations folder.
now add migration with message for current project, run add-migration InitialCreate
to update Database, run update-database
Refresh/Reconnect you server/db. You will find the db there.
Related
I am assuming there is something I am missing but when I generate migrations in a project, they keep showing empty Up and Down methods. Even in a brand new project. Here are my steps.
Launch Visual Studio 2019. Create a new ASP.NET Web Application (.net framework) C# project (4.7.2). Choose MVC and under authentication select Individual User Accounts. Click create to create the project.
Next I Enable Migrations.
Enable-Migrations
Next I add my first migration.
Add-Migration First
A first migration is successfully added with all the identity information for individual user accounts. All is good.
I update the database to apply the migration. All is still good.
Update-Database
Now, I add a new class to the Models folder called SchoolContext.
using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
namespace WebApplication6.Models
{
public class SchoolContext : DbContext
{
public DbSet<Student> Students { get; set; }
public SchoolContext() : base("DefaultConnection") { }
}
public class Student
{
[Key]
public int StudentID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
}
}
I now go back to the Package Manager Console to create another migration. I attempt to create a new migration.
Add-Migration Second
But this time, the class is empty. it does not create my new table.
namespace WebApplication6.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Second : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
}
What am I missing? Why doesn't it want to generate a migration with my new table?
As requested, this is what my ApplicationDbContext looks like in my IdentityModel.cs class generated by Visual Studio.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
If your first migration created users tables, then I assume that it used IdentityDbContext. Then, you need to inherit your SchoolContext not from DbContext, but from IdentityDbContext.
UPDATE: based on the latest update of the question, it is clear that application already has one database context, which is ApplicationDbContext. So usually it is enough to keep all DbSet<> in one database context. No need to create new context.
You are missing the dbset property.
Put it as following example so that migrations can detect the new class/table.
After adding the dbset property, add new migration to see the new class written.
If you already have a migration pending then write -force for the code to see new changes and update migration
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("DefaultConnection") {
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
public virtual DbSet<Student> Students { get; set; }
}
Note that there are 2 dbcontexts which is not of clear use, use only ApplicationDBContext and remove the other.
I have data in a SQLite Database. But I can not be sure that it will always be there. So when I start my Program I first want to check if the SQLite Database exists and when not I want to create one with the DbSet's I already have in my DbContext.
public class MaintenanceDB : DbContext
{
public MaintenanceDB() : base (new SQLiteConnection(new
SQLiteConnectionStringBuilder { DataSource = "data.sqlite"}.ConnectionString), true)
{
}
public DbSet<MaintenanceEntry> MaintenanceEntries { get; set; }
public DbSet<ModuleEntry> ModuleEntries { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MaintenanceEntry>().ToTable("some Table");
modelBuilder.Entity<ModuleEntry>().ToTable("some Table");
}
}
When I delete my SQLite Database and startup my Program again then I want my SQLite Database to be created.
<connectionStrings>
<add name="MaintenanceDB" connectionString="" providerName="System.Data.SqLite" />
</connectionStrings>
public class MaintenanceDB : DbContext
{
public MaintenanceDB() : base ("Name=MaintenanceDB")
And try the solutions below:
var context = new MaintenanceDB();
if (!context.Database.Exists())
context.Database.Create();
Or
var context = new MaintenanceDB();
context.Database.CreateIfNotExists();
Or create an initializer class as below:
// public class ContentInitializer: DropCreateDatabaseAlways <MaintenanceDB>
// public class ContentInitializer: CreateDatabaseIfNotExists <MaintenanceDB>
public class ContentInitializer: DropCreateDatabaseIfModelChanges <MaintenanceDB>
And put this at the beginning of the application.
Database.SetInitializer (new ContentInitializer ());
I want to use the Scaffolding Mechanism in the Entity Framework to create a MusicDBContext database and table automatically, but a problem occurred when I was programming.
The creation of steps shown below:
1. Create a console application.
2. Use the NuGet to install the Entity Framework: PM> install-package Entity Framework
3. Insert the following code into the configuration Session in App.Config:
<connectionStrings>
<add name="MusicDBContext"
connectionString="Data Source=(LocalDb)\MSSQLLocalDB;
Initial Catalog=MusicDBContext;Integrated Security=SSPI;
AttachDBFilename=|DataDirectory|\MusicDBContext.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>
4. Write the following code in the console:
using System;
using System.Linq;
using System.Data.Entity;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
try
{
MusicDbContext db = new MusicDbContext();
Music music = new Music { Title = "Far Away From Home",
ReleaseDate = DateTime.Now };
db.Musics.Add(music);
db.SaveChanges();
db.Musics.ToList().ForEach(x => Console.WriteLine($"{x.ID},
{x.Title},{x.ReleaseDate}"));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
if(ex.InnerException != null)
{
Console.WriteLine(ex.InnerException.Message);
}
}
Console.ReadKey();
}
}
public class Music
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { set; get; }
}
public class MusicDbContext : DbContext
{
public MusicDbContext() : base("MusicDBContext") { }
public DbSet<Music> Musics { set; get; }
}
}
However, the following error occurred during runtime:
A file activation error occurred.
The physical file name '\\MusicDBContext.mdf' may be incorrect.
Diagnose and correct additional errors, and retry the operation.
CREATE DATABASE failed. Some file names listed could not be created.
Check related errors.
When I delete all the content in the connectionStrings session, it runs OK.
Entity Framework uses the default connection of SqlLocalDB.
ConnectionString shown below:
Data Source=(localdb)\\mssqllocaldb;Initial Catalog=MusicDBContext;Integrated Security=True;MultipleActiveResultSets=True
Why is there a problem with the connection named MusicDBContext?
The keyword DataDirectory has problem?
Good Day,
I understand so far that EF tries to have the developer work in a code-first paradigm. I am having trouble with my setup at the moment because EF wants to Create a database - and it is being denied. I have already created a database and also changed the generated database connection string to where I want it to connect - and which database to use.
I haven't extensively used EF in my career, but I see a growing need for it over the ADO.NET approach. I have decided to try my hand at it. Here is what I have:
Connection String
<add name="DefaultConnection" connectionString="Data Source=EON-PC\2008;Initial Catalog=Experimental;Integrated Security=true;" providerName="System.Data.SqlClient" />
MVC Models
namespace EFExperiment.Models
{
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
[Table("stores")]
public class Stores
{
[Key]
public string Id { get; set; }
public string StoreName { get; set; }
public string AdminEmail { get; set; }
public string Url { get; set; }
}
public class StoreDbContext : DbContext
{
public StoreDbContext()
{
//Database.SetInitializer<StoreDbContext>(null); //Tried this - also failed. It didn't try to create a database here
}
public DbSet<Stores> Stores { get; set; }
}
}
Controller
namespace EFExperiment.Controllers
{
using EFExperiment.Models;
using System.Linq;
using System.Web.Mvc;
public class StoresController : Controller
{
private StoreDbContext db = new StoreDbContext();
public ActionResult Index()
{
return View(db.Stores.ToList());
}
}
}
Error:
CREATE DATABASE permission denied in database 'master'.
What confuses me now is - how do you use EF when it is intended to wipe and recreate your DB? Am I missing something here? I would like to read from my actual tables in my DB, along with other CRUD operations - not have it recreate it every time I run my application.
How can Entity Framework detect if it is created from SQL Server or Oracle by code? Is there any
property or method which returns the source database type?
Entity Framework knows it from connection being used in DbContext (either from connection string, because it has Provider part or from instance itself directly). You can get the "type" from DbContext.Database.Connection. I.e.:
DbContext.Database.Connection.GetType().Name
I can't think of a better way of doing this than getting the DbProviderFactory and checking its type.
If you create a class library solution and install the NUnit and EntityFramework nuget packages you can run the below.
using System.Data.Common;
using System.Data.Entity;
using System.Diagnostics;
using NUnit.Framework;
namespace efProviderChooser
{
public class MyThing
{
public int Id { get; set; }
}
public class MyContext : DbContext
{
public DbSet<MyThing> Things { get; set; }
}
public class Test
{
[Test]
public void CanGetProvider()
{
var context = new MyContext();
var dbProviderFactory = DbProviderFactories
.GetFactory(
context.Database.Connection);
Debug.WriteLine(dbProviderFactory.GetType());
//gives one of
//System.Data.EntityClient.EntityProviderFactory
//System.Data.Odbc.OdbcFactory
//System.Data.OleDb.OleDbFactory
//System.Data.OracleClient.OracleClientFactory
//System.Data.SqlClient.SqlClientFactory
//this list could change!
// here I get SqlClient
Assert.That(dbProviderFactory.GetType().ToString().Contains("SqlClient"));
}
}
}