Use MDF with entityframework Core - c#

I'm trying to figure out how to connect to an .mdf file using entityframework core. I found a resource on how to connect to one here However it doesn't seem to be working. I've made a var simple context using the Northwind dataset
public class Order
{
public int OrderId { get; set; }
public string CustomerID { get; set; }
public int EmployeeID { get; set; }
public DateTime OrderDate { get; set; }
// etc.
}
public class NorthwindContext : DbContext
{
public NorthwindContext(DbContextOptions options) : base(options) { }
public DbSet<Order> Orders { get; set; }
}
I've created a test class to attempt to connect to the DB
public string NorthwindConnectionString = #"Data Source=.\SQLEXPRESS;
AttachDbFilename=C:\source\Astoot\RestEzCore.Tests\TestDB\NORTHWND.MDF;
Integrated Security=True;
Connect Timeout=30;
User Instance=True";
[TestMethod]
public void TestMethod1()
{
var optionsBuilder = new DbContextOptionsBuilder<NorthwindContext>();
//I've also tried UseSqlLite()
optionsBuilder.UseSqlServer(this.NorthwindConnectionString);
using (var context = new NorthwindContext(optionsBuilder.Options))
{
var orders = context.Orders.ToList();
Assert.IsTrue(orders.Any());
}
}
However when I attempt to run my tests I get an error
instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections
Edit
I've also tried moving my MDF to users folder and connect using this connection string:
Data Source=(LocalDB)\MSSQLLocalDB;DataBase=Northwind;Integrated Security=True;Connect Timeout=30"
However this doesn't seem to work as well, it throws an exception
SqlException: Cannot open database "Northwind" requested by the login. The login failed.
Login failed for user 'MyUser'
Is there something wrong with my connection string?
I can't quite seem to figure out how to use an MDF with entityframework

I did some investigation, and it turns out that it was returning a bogus error because Northwind DB in built from SQL Server 2000, and I'm running SQL server 2016 so Instead I Created a Sample DB and used that as an MDF.
Now my connection string looks like so:
public static string MDF_Directory
{
get
{
var directoryPath = AppDomain.CurrentDomain.BaseDirectory;
return Path.GetFullPath(Path.Combine(directoryPath, "..//..//..//TestDB"));
}
}
public string astootConnectionString = "Data Source=(LocalDB)\\MSSQLLocalDB; " +
"AttachDbFilename="+ MDF_Directory + "\\Astoot.mdf;" +
" Integrated Security=True; Connect Timeout=30;";

Related

Generating database per tenant using EF C#

I am building a multi-tenant application using C# EF Code First approach.
I am opting for separate DB per tenant. In this regard, when the application loads the tenant can login or register.
This is how registration page looks like.
On submit, I capture this tenant details in the common DB with name MyAppDB & table tblTenants
Here Tenant name is unique & on successful submission of the form, I need to create new DB on the same server with Tenant name & generate set of tables for the Models.
This is my model looks like for every Tenant.
public class Product
{
public int Id { get; set;}
public string Name { get; set;}
}
public class Sales
{
public int Id { get; set;}
public string Name { get; set;}
}
How do I generate this Models to tables using C# EF Code First approach??
Thanks.
Seems like you have two questions.
How do I create a database programmatically on an SQL Server?
If you don't want any dependencies in your code, you can run run sql commands directly against your sql server:
using (var connection = new SqlConnection(myConnectionString))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "CREATE DATABASE mydb";
command.ExecuteNonQuery();
}
Bam you got your new db, the connection string for your new db will be "Data Source=ServerName;Initial Catalog=mydb;Integrated Security=False;User Id=sa;Password=password;MultipleActiveResultSets=True"
How do I create tables in the new db using EF code-first?
You don't necessarily, you let EF deal with this.
Create your tenantdbcontext class:
public class TenantDbContext : DbContext
{
public TenantDbContext () : Base("name=yourConnString") { }
public DbSet<Product> Products { get; set; }
public DbSet<Sales> Sales { get; set; }
}
In your code when you need to access those tables use
TenantDbContext tdc = new TenantDbContext();
tdc.Products.Add(new Product)
Your challenege will be in using the appropriate connection strings to appropriate contexts according to which tenant you are working with.
Here is how I have addressed my requirement currently.
When any new user/tenant submits the form,
First, I am inserting user/tenant details into common/master DB
Then I create a new DB with Tenant Name on the server.
Submit Action:-
[HttpPost]
public ActionResult CreateTenant(Tenanat tenanat)
{
//Master/Common DB
using (DataContext ctx = new DataContext())
{
ctx.Tenanats.Add(tenanat);
ctx.SaveChanges();
string con = ConfigurationManager.ConnectionStrings["tenantContext"].ConnectionString;
con = con.Replace("tenDbName", tenanat.Name.Trim());
TenantContext tenantContext = new TenantContext(con,tenanat);
}
return RedirectToAction("Index", "Tenanat",tenanat);
}
This is what my TenantContext class looks like which is handling the primary stuff to generate the DB on demand.
public class TenantContext : DbContext
{
public TenantContext(string connection, Tenanat tenanat)
: base(connection)
{
//create DB for tenant
Database.CreateIfNotExists();
//create user for the new Db
string sql = "CREATE LOGIN \"" + tenanat.Email + "\" WITH PASSWORD = '" + tenanat.Password + "'; USE " + tenanat.Name + "; CREATE USER \"" + tenanat.Email + "\" FOR LOGIN \"" + tenanat.Email + "\" WITH DEFAULT_SCHEMA = dbo;";
Database.ExecuteSqlCommand(sql);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
public DbSet<Product> Products { get; set; }
public DbSet<Order> Orders { get; set; }
}}
Please feel free to validate this approach & add suggestions.
Hope this helps!!

Entity Framework Core 2 Migration issue

I am building app using ASP.NET Core 2 and DB part is EF core 2.
i have model like this
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
This is context file
public class EFCoreDbContext:DbContext
{
public EFCoreDbContext(DbContextOptions<EFCoreDbContext> options)
: base(options)
{
}
public DbSet<ChatMessage> ChatMessages { get; set; }
}
and finally startup.cs
services.AddDbContext<EFCoreDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MooltiRoomDatabase")));
And connection string in appsettings.json
"ConnectionStrings": {
"MooltiRoomDatabase": "Server=DESKTOP-BCQ6IAU\\CHATDB,Database=MultiRoomChat;Trusted_Connection=True;"
}
Through package manager console i was runing Add-Migration the command completed successfully despite the fact that in DB it did not create corresponding table,after that i've read that i need to run Update-Database command for creating table and when i run this command, i got a error like this
A network-related or instance-specific error occurred while
establishing a connection to SQL Server. The server was not found or
was not accessible. Verify that the instance name is correct and that
SQL Server is configured to allow remote connections. (provider: SQL
Network Interfaces, error: 25 - Connection string is not valid)
As you can see in the error message, 'Connection string is not valid.' You used "," instead of ";" before the Database.
So now you have:
"Server=DESKTOP-BCQ6IAU\\CHATDB,Database=MultiRoomChat;Trusted_Connection=True;"
But, you should use this:
"Server=DESKTOP-BCQ6IAU\\CHATDB;Database=MultiRoomChat;Trusted_Connection=True;"
In ASP Net Core there is also a development configuration that gets used. You should notice an icon next to app settings - the "drop down" icon. See if adding your connection string to the development config helps.
Also the way the app settings get accessed has changed so make sure you are writing the correct code to receive the value.

Error when creating and connecting to Entity Framework database on an Azure virtual machine

I created an virtual machine on Azure with VS2017 installed on it. Then, I tried to clone a project I'm working on that works on adding elements to a database using Entity Framework code-first.
But I get this error when trying to run the project:
Unhandled Exception: System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)
Any idea how to resolve this?
(N.B. the project is working fine on my local machine)
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible.
If your SQL Server instance is hosted on your local network, please make sure whether it has been configured that it can be remote access. If it can't be remote access, I am afraid you need to migrate your SQL Server database to your Virtual Machine or Azure SQL. Then you could modify your connection string to access the new database which can be accessed from your project.
I don't want to migrate anything, I want to make a new database on the VM..
You could use Local DB which works on your VM. If your application type is web application, you could modify your database as following. EF will create a new database in your App_Data folder.
Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\Database1.mdf;Integrated Security=True
Otherwise, you need to put the detail configure the detail path of your database file in the connection string. For example,
Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=D:\Database1.mdf;Integrated Security=True
I just tested the LocalDB on Azure Windows 10 virtual machine with VS 2017 installed and it can create database when I use EF code first. Following is my test code.
class Program
{
static void Main(string[] args)
{
using (SchoolContext context = new SchoolContext())
{
context.Students.Add(new Student { ID = 1, FirstMidName = "FMN", LastName = "LN", EnrollmentDate = DateTime.Now });
context.SaveChanges();
}
Console.Write("Create database OK");
Console.Read();
}
}
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
}
public class SchoolContext : DbContext
{
public SchoolContext() : base(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\amor\Desktop\TestEF\CodeFirstSample\Database1.mdf;Integrated Security=True")
{
}
public DbSet<Student> Students { get; set; }
}

Mysql custom connection string

I have entity framework 5 with the mysql connector installed (mysql for vs 1.1.3 and mysql connector 6.8.3) and have a connection string in my app.config:
<add name="applicantDBEntities" connectionString="metadata=res://*/Models.applicantsDBModel.csdl|res://*/Models.applicantsDBModel.ssdl|res://*/Models.applicantsDBModel.msl;provider=MySql.Data.MySqlClient;provider connection string="server=localhost;user id=root;database=applicantsdb"" providerName="System.Data.EntityClient" />
If I use the connection string in the app.config, everything works, but I want the user to be able to choose his server, username, password and DB. How i tried to implement it:
public partial class applicantDBEntities : DbContext
{
public applicantDBEntities()
: base("name=applicantDBEntities")
{
}
public applicantDBEntities(string connectionString) : base (connectionString)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<applicant> applicants { get; set; }
public DbSet<file> files { get; set; }
}
And the initialization itself:
CONNECTION_PATTERN = "server={0};database={1};User Id={2};password={3}";
this.dbContext = new applicantDBEntities(String.Format(CONNECTION_PATTERN,
Settings.GetInstance().Server, Settings.GetInstance().Database,
Settings.GetInstance().User, Settings.GetInstance().Password));
but no matter what I pass as arguments (even wrong ones) I always end up in the OnModelCreating method.
What is the correct way to do this?
EDIT:
As #Andrew mentioned, my connection string was wrong. This is how I do it now:
string connectionString = new System.Data.EntityClient.EntityConnectionStringBuilder
{
Metadata = "res://*",
Provider = "MySql.Data.MySqlClient",
ProviderConnectionString = new System.Data.SqlClient.SqlConnectionStringBuilder
{
InitialCatalog = Settings.GetInstance().Database,
DataSource = Settings.GetInstance().Server,
IntegratedSecurity = false,
UserID = Settings.GetInstance().User,
Password = Settings.GetInstance().Password
}.ConnectionString
}.ConnectionString;
this.dbContext = new applicantDBEntities(connectionString);
Your connection string is in invalid format.
It should resemble this:
"metadata=res://*/Northwind.csdl|
res://*/Northwind.ssdl|
res://*/Northwind.msl;
provider=System.Data.SqlClient;
provider connection string=
"Data Source=.\sqlexpress;
Initial Catalog=Northwind;
Integrated Security=True;
MultipleActiveResultSets=True""
and might be based on EntityConnectionStringBuilder
http://msdn.microsoft.com/en-us/data/jj592674.aspx here's description of how you should connect to database for different scenarios and framework versions

Why can't SQL Server Compact Edition open an existing SDF file if my connection string contains the max database size keyword?

I keep seeing this exception:
ex = {"Keyword not supported: 'max database size'."}
When I try running the following code (exception is thrown on the LINQ query line):
LogContext l = new LogContext(connectionString);
var v = from log in l.Logs select log;
count += v.Count();
The LogContext class looks like this:
public class LogContext : DbContext
{
public LogContext()
: base()
{
}
public LogContext(string connectionString)
: base(connectionString)
{
}
public DbSet<LogRecord> Logs { get; set; }
}
My connection string contains the Max Database Size property. Is there a reason why its throwing this exception? Does SQL Server Compact Edition use the Max Database Size property only once for creating the database and stores this information in the local file or something, such that I can't connect to this file when I specify this property thereafter? Because this all works when I create new databases.
Setting the DefaultConnectionFactory seemed to work for me:
Database.DefaultConnectionFactory = new
SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");

Categories

Resources