entity framework cannot open database - entity-framework

I'm following the EF - Code First example at http://msdn.microsoft.com/en-us/data/jj193542.aspx. This example works fine. The example creates a LocalDB on my harddrive containing the database files .mdf and .ldf.
If I delete these 2 files, I get a Cannot open database exception, if I replace the files, it works. If I change the name of my DbContext and it will work.
Heres my question:
Why do I not get an exception when I first run the example ? Something somewhere appears to remember the filename/context name. What is the correct way to handle this ?
Class and DBContext below, exception throw at db.Blogs.Add(blog);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
class Program
{
static void Main(string[] args)
{
using (var db = new BloggingContext())
{
// Create and save a new Blog
Console.Write("Enter a name for a new Blog: ");
var name = Console.ReadLine();
var blog = new Blog { Name = name };
db.Blogs.Add(blog);
db.SaveChanges();
// Display all Blogs from the database
var query = from b in db.Blogs
orderby b.Name
select b;
Console.WriteLine("All blogs in the database:");
foreach (var item in query)
{
Console.WriteLine(item.Name);
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}

This actually doesn't have anything to do with your code. LocalDB will create a new database for you if one doesn't exist. The problem with removing the mdf/ldf files is that you're deleting the files without letting LocalDB know. So as far as it's concerned, the database still exists but the files backing the database are missing.
To delete a LocalDB database properly, use Server Explorer or SQL Object Explorer in Visual Studio (SQL Management Studio should work too). If the database file is in the app_data folder of your web project, deleting the file from Solution Explorer should properly delete the database as well.

What I was really trying to do was understand how/where a database is generated via a Code First approach. After some research, it turns out its pretty simple. All you need to do is create a connection string in your app.config or web.config file, something along the lines of ...
<connectionStrings>
<add name = YourDBContextName
providerName = "System.Data.SqlClient"
connectionString = "Data Source = (localdb)\v11.0; AttachDbFilename = Path to MDF file ...
The AttachDbFile specifies where the database will be created. You have to also name the connection the same as your database context.

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);
}
}

SocketException while trying SaveChanges on a list of blobs with Entity Framework and MariaDB using Pomelo NUGET package

I would like to switch from SQLExpress to MariaDB, but run into an issue with SaveChanges.
I can replicate the exception related to the byte[] with a console test application easily using this code, which runs perfectly if I try the same on SQLExpress.
What puzzles me is:
TestScenario 1: Put the byte[] into TestTable class, it works with MariaDB.
TestScenario 2: Replace the list of SubTable with just one instance of subtable. -> Works
TestScenario 3: Replace the byte[] in SubTable by e.g. a single int -> again works
Each time I used add-migration and update-database prior to running the code.
The error message I am getting is:
"SocketException: Eine bestehende Verbindung wurde softwaregesteuert
durch den Hostcomputer abgebrochen."
"SocketException: Failed to read the result set."
I am using the latest version from Pomelo as well as EFCore via NUGET manager.
Honestly I am at a loss. The only information I could find on google was to check the maximum package size setting, but this is well above the blob size for my DB.
So here is my code:
A simple TestTable class with a List of SubTables.
public class TestTable
{
public int ID { get; set; }
public List<SubTable> sub { get; set; } = new List<SubTable>();
}
public class SubTable
{
public int ID { get; set; }
public int ParentID { get; set; }
public SubTable Parent { get; set; } //<- see Update Mai, 19th, 2020 below
public byte[] blob { get; set; } //<- here is the root cause for the issue (see Update Mai, 19th, 2020)
}
SubTable contains the blob as an array of bytes.
The ModelContext is derived from DBContext so nothing fancy here. Just the connection string, which needs to be adapted to the specific system.
public partial class ModelContext : DbContext
{
public DbSet<TestTable> TestData { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySql(#"Server=<IP>;Database=<DB>;User Id=<ID>;Password=<PW>;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
}
In the main part of the console app, I create the ModelContext and initialize my datastructure. I am using Code-First approach, having the database created by using add-migration and update-database.
class Program
{
static void Main(string[] args)
{
using (var db = new ModelContext())
{
TestTable t = new TestTable();
for (int index = 0; index < 4000; index++)
t.sub.Add(new SubTable() { blob = new byte[5000] });
db.TestData.Add(t);
db.SaveChanges(); // <- at this point the exception is raised
}
Console.WriteLine("Done!");
}
}
}
This is how the migration part of subtable looks like:
migrationBuilder.CreateTable(
name: "SubTable",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ParentID = table.Column<int>(nullable: false),
blob = table.Column<byte[]>(nullable: true),
TestTableID = table.Column<int>(nullable: true)
},
So basically this is a standard scenario which can be found on numerous web sites and blogs, if there would not be the exception, which I do not understand.
Any help/suggestions apprechiated.
UPDATE 2020 Mai 19:
Out of curiosity, I again tried to solve the issue. So I installed the newest version of MariaDB.
I received an error message indicating something is wrong with the
foreign key design.
Double checking the foreign key, I found a bug
in my code. public SubTable Parent { get; set; } should be:
public TestTable Parent { get; set; }
--> Now it works just fine with the newest version of MariaDB.
The MariaDB version (V5.5.xx) running on my NAS won't though. Sad but definetly not a show stopper.
So for me the issue is closed, as it seems to be related to an outdated version of MariaDB.
Cheers,
Axel

Swagger-net breaks when using [FromUri] with a complex EF model

I'm using Swagger-Net in my .NET 4.5.1 WebAPI project and one of my API calls is causing the Swagger UI to spin forever on load before coming back with the error below.
Specifically, I found that using [FromUri] in combination with a complex EF entity that has references to other entities ends up causing this.
[HttpPost]
public APIResponse CreateSchool([FromUri]School school)
{
// save school object to db
}
public partial class School : IAuditableEntity,IEntity
{
public School()
{
this.Affiliations = new HashSet<Affiliation>();
this.SchoolAccreditations = new HashSet<SchoolAccreditation>();
this.SchoolAdultRoles = new HashSet<SchoolAdultRole>();
this.SchoolCareOptions = new HashSet<SchoolCareOption>();
this.SchoolDailySessions = new HashSet<SchoolDailySession>();
this.SchoolEligibilityRequirements = new HashSet<SchoolEligibilityRequirement>();
// ...more hashsets
[DataMember]
public int SchoolID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public bool Active { get; set; }
//...more properties
}
}
Is there a way to still use FromUri and the EF model? Or do I need to change my API call signature?

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.

Programmatically creating a connection string for mapping an Entity Framework Code-First model with an existing Sql Server Compact database

I've successfully mapped an Entity Framework Code-First data model with an existing Sql Server Compact database by a declarative approach using app.config but it would be great if I could build such connection programmatically with perhaps the help of the EntityConnectionStringBuilder (System.Data.EntityClient) class. Unfortunately this approach is not working as the [DbContext].Connection.ConnectionString is not accepting most of its properties.
Here's the actual working code with the faulty one commented out:
Book.cs
public class Book
{
[Key]
public string Isbn { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public string Publisher { get; set; }
public DateTime Published { get; set; }
public int Pages { get; set; }
public bool InStock { get; set; }
public string Description { get; set; }
}
Catalog.cs
public class Catalog : DbContext
{
public DbSet<Book> Books { get; set; }
}
app.config
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add
name="Catalog"
providerName="System.Data.SqlServerCE.4.0"
connectionString="Data Source=res/Catalog.sdf"
/>
</connectionStrings>
</configuration>
Main()
static void Main()
{
// var res = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "res");
// var str = new EntityConnectionStringBuilder();
// str.Name = "Catalog";
// str.Provider = "System.Data.SqlServerCe.4.0";
// str.ProviderConnectionString = String.Format("Data Source {0}", Path.Combine(res, "Catalog.sdf"));
try
{
using (var catalog = new Catalog())
{
// catalog.Database.Connection.ConnectionString = str.ConnectionString;
// remaining code not relevant - skipped
I've tried using other builder classes such as SqlCeConnectionStringBuilder (System.Data.SqlServerCe), SqlConnectionStringBuilder (System.Data.SqlClient) and even DbConnectionStringBuilder (System.Data.Common) but apparently none of them seem to match what [DbContext].Connection.ConnectionString is expecting.
Should I conclude there is no programmatic way to achieve this?
Any advice will be surely appreciated. Thanks much in advance for your contributions.
If you are using SQL Server Compact 4.0 and DbContext with code first you cannot use EntityConnectionStringBuilder - it builds connection string for EF with EDMX file. You need SqlCeConnectionStringBuilder from System.Data.SqlServerCe assembly with version 4.0.0.0!
You should also pass the connection string to the context instance through the constructor - DbContext has constructor accepting name of the connection string (from configuration) or connection string itself.
Open a DbConnection and pass it to the DbContext constructor or use a DefaultConnectionFactory:
Database.DefaultConnectionFactory
= new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
using (var catalog = new Catalog("Catalog.sdf"))
{
}
SqlCeConnectionFactory is a ready-to-use connection factory provided by Microsoft, but you can also implement your own factory.