entity framework ConnectionTimeout not work - entity-framework

I am using entity framework 6.0, and here is how I set the connection timeout:
DbContext cc = new DbContext("Data Source=VLT180;Initial Catalog=VISTAIT;Persist Security Info=True;User ID=XXXXXXXX;Password=XXXXX;Connect Timeout=6");
cc.Database.ExecuteSqlCommand("select * from table1");
but this does not work, when I disconnect my network, the code will hang at the "ExecuteSqlCommand" method infinitely. if I reconnect my network, it works correctly as expected.
I am using the latest entity framework: 6.1.3
Is there any clue?

Your Context must look like
public class Context : DbContext
{
public Context(string connectionString) : base(connectionString)
{
}
public DbSet<Quote> Quote { get; set; }
}
Then you can execute raw sql as follows
using (var context = new Context())
{
var quotes = context.Quote.SqlQuery("SELECT * FROM dbo.Quote").ToList();
}
You execute sql on the dbset Quote.

Related

Entity Framework Code First Initial Create

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

Connection string for code first mode with mysql

I am working on a project that gets connection strings for Entity Framework from environment variables, like this:
public class SomeTests {
[Fact]
public async void TestSomething() {
string connectionString = Environment.GetEnvironmentVariable("APP_CONN_STR");
var appContextOptionsBuilder = new DbContextOptionsBuilder<AppDataContext>();
appContextOptionsBuilder.UseMySql(connectionString); // hardcoded mysql
AppDataContext context = new AppDataContext(appContextOptionsBuilder.Options);
Assert.Equal(context.Country.Count(), 0);
}
}
....
public partial class AppDataContext : DbContext, IAppDataContext
{
public AppDataContext(DbContextOptions options) : base(options)
{
}
public virtual DbSet<Country> Country { get; set; }
...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Country>(entity =>
{
entity.ToTable("country");
...
});
...
}
}
The code above is a bootstrapper code for some automated integration testing. Historically every developer is using the same old database instance on the network without a problem. I am trying to make these tests run in an isolated environment, so I have set up an empty new mysql database (using docker to make it reproducible), and let Entity Framework to populate it with a schema.
The problem is, when I create an empty database in this mysql instance and give a connection string to that database, then I am getting table not found errors:
connection str: Server=127.0.0.1;Port=3306;Database=app_mysql_db;Uid=root;Pwd=****;
error: MySql.Data.MySqlClient.MySqlException : Table 'app_mysql_db.country' doesn't exist
I found out that EF will not create tables in existing databases, it will only populate a database with tables if EF itself created it. This is the default behavior of EF.
So I tried to remove the database name from the connection string:
connection str: Server=127.0.0.1;Port=3306;Uid=root;Pwd=****;
error: MySql.Data.MySqlClient.MySqlException : No database selected
So how do I let Entity Framework in Code First mode to create my tables?

Entity Framework 6 Programmatically Connect to Postgres

I'm working on programmatically establishing a connection to PostgresSQL using Entity Framework 6. I have this class:
public class ClearspanDatabaseContext : DbContext
with this constructor:
public ClearspanDatabaseContext()
: base(buildConnectionString())
{
}
Here's the static method that makes the connection string programmatically:
private static string buildConnectionString()
{
RegisterDbProvider("Npgsql", ".Net Framework Data Provider for Postgresql", "Npgsql Data Provider", "Npgsql.NpgsqlFactory, Npgsql");
EntityConnectionStringBuilder entityConnectionStringBuilder = new EntityConnectionStringBuilder();
entityConnectionStringBuilder.Provider = "Npgsql";
entityConnectionStringBuilder.ProviderConnectionString = "host=192.168.168.140;Port=5432;username=ClearspanDevLogin;password=*******;database=ClearspanWebServerDev";
return entityConnectionStringBuilder.ToString();
}
And here's the method that registers Npgsql as a database provider, taken from this source:
public static bool RegisterDbProvider(string invariant, string description, string name, string type)
{
try
{
DataSet ds = ConfigurationManager.GetSection("system.data") as DataSet;
foreach (DataRow row in ds.Tables[0].Rows)
{
if (row["InvariantName"].ToString() == invariant)
{
return true;
}
}
ds.Tables[0].Rows.Add(name, description, invariant, type);
return true;
}
catch
{
}
return false;
}
This generates a string like this:
"provider=Npgsql;provider connection string=\"host=192.168.168.140;Port=5432;username=ClearspanDevLogin;password=********;database=ClearspanWebServerDev\""
But I get an ArgumentException:
Keyword not supported: 'provider'.
I think I am close to the programmatic connection, but am missing something small. What can I do to resolve this exception and properly setup this connection programmatically? No app.config answers, I'm working in a class library, which ignores app.config (see the comments of the accepted answer to this question). This program must remain this way because it is used as a plugin - it does not (nor should it) run on its own. Thanks in advance.
Ok, here is working example for you which I verified is working.
Using dummy code-first EF 6 model + custom DbConfiguration class:
public class Enrollment {
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
}
[DbConfigurationType(typeof (NpgsqlConfiguration))]
public class SchoolContext : DbContext {
public SchoolContext(string cs) : base(cs) {
}
public DbSet<Enrollment> Enrollments { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
}
}
class NpgsqlConfiguration : System.Data.Entity.DbConfiguration
{
public NpgsqlConfiguration()
{
SetProviderServices("Npgsql", Npgsql.NpgsqlServices.Instance);
SetProviderFactory("Npgsql", Npgsql.NpgsqlFactory.Instance);
SetDefaultConnectionFactory(new Npgsql.NpgsqlConnectionFactory());
}
}
Then, instead of your buildConnectionString(), just pass postgre connection string in constructor:
using (var ctx = new SchoolContext("host=192.168.168.40;port=5432;...")) {
Console.WriteLine(ctx.Enrollments.ToArray());
}
And that is all. Config file is completely empty during that, and it works.
Have you looked at Code-Based Configuration? Create a DbConfiguration class with a public parameterless constructor in the same assembly as your DbContext
class MyConfiguration : System.Data.Entity.DbConfiguration
{
public MyConfiguration()
{
SetProviderServices("Npgsql", Npgsql.NpgsqlServices.Instance);
SetProviderFactory("Npgsql", Npgsql.NpgsqlFactory.Instance);
}
}
Now I think the DbContext should use that provider factory by default, and you can construct the DbContext with just the connection string. But if it's in a different assembly, then you have a bit more work to do, but that can be found in the link above.
A potential problem with the above solution is that any configuration in the config file will take precedence, so maybe it would be safer to use the option described in here:
var conn = DbProviderFactories.GetFactory("MY_CONN_PROVIDER").CreateConnection();
conn.ConnectionString = "MY_CONN_STR";
new DbContext(conn, true);
where your provider is "Npgsql", which was registered in RegisterDbProvider above.
Also see https://msdn.microsoft.com/en-us/library/dd0w4a2z(v=vs.110).aspx

Entity framework 6 connecting multiple database implemention advice

I am a novice when it comes to entity framework.I usually use ado.net because is faster than any ORM and the repetitive code can be easily generated.
Now I have decided to give EF6 a go again and gain some experience in EF
Scenario.
Need to migrate data for many clients.(30 databases)
Each client will have their own staging database
Each database will have different tables
All databases will have/share the same "Views" schema.
Basically we decided that regardless of the clients tables ,they must all share the same Views.
So when we read the data we dont care because the views columnNames will be the same for them all.
Ado.net Implementation
Is very simple.I my dal i have methods like "GetCustomers","GetAccounts" etc... and all I need to do is change the connectionString
and I can read the views from any database.Does not get simpler than this.
EF implementation
Please correct me if I am wrong.
In order for EF to work I would have to generate code for 30 databases (databaseFirst).
Is there a way I can use just a connection string to connect to the right database and based on that connection string read data from the views?
How would you do it using EF6 by just changing the connection string?
Can you give a noddy example how to do it?
Any suggestions
here it is, just a bit more of 10 minutes... (EF 5 on .net 4.5)
using System;
using System.Linq;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.Data.Objects.SqlClient;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Data.SqlClient;
namespace testef {
public class EntityZ {
public Int32 Id { get; set; }
public String P1 { get; set; }
}
public class EntityZConfiguration : EntityTypeConfiguration<EntityZ> {
public EntityZConfiguration()
: base() {
ToTable("v", "dbo"); // the view
HasKey(x => x.Id); //required
//the mapping of properties
Property(x => x.Id).HasColumnName("id");
Property(x => x.P1).HasColumnName("value");
}
}
public class TestEFContext : DbContext {
public DbSet<EntityZ> Entities { get; set; }
public TestEFContext(String cs)
: base(cs) {
//Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
Database.SetInitializer<TestEFContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new EntityZConfiguration());
}
}
class Program {
static void Main(string[] args) {
//creating the db
using (SqlConnection conn = new SqlConnection("Data Source=ALIASTVALK;Initial Catalog=master;Integrated Security=True; MultipleActiveResultSets=True")) {
conn.Open();
using (SqlCommand com = conn.CreateCommand()) {
com.CommandText = "declare #v int = 0 select #v = 1 from sys.databases where name = 'TestEF' if #v = 1 drop database TestEF";
com.ExecuteNonQuery();
com.CommandText = "create database TestEF";
com.ExecuteNonQuery();
com.CommandText = "use TestEF";
com.ExecuteNonQuery();
com.CommandText = "create table t (i int not null, t nvarchar(max))";
com.ExecuteNonQuery();
com.CommandText = "insert into t (i, t) values (1, 'hello world')";
com.ExecuteNonQuery();
com.CommandText = "create view v as select i as id, t as value from t";
com.ExecuteNonQuery();
}
}
String cs = #"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True";
using (TestEFContext ctx = new TestEFContext(cs)) {
foreach (EntityZ z in ctx.Entities) {
Console.WriteLine("{0}: {1}", z.Id, z.P1);
}
}
}
}
}

Unable to determine the provider name for connection of type 'System.Data.SqlServerCe.SqlCeConnection'

i am using the Ado.Net Entity Framework with Code Only (Tutorial at: ADO.NET team blog) and i want to be as much database independent as possible.
In my first approach i just want to go for Sql Express and Sql Compact databases.
With Sql Express everthing works fine but with Sql Compact i get the exception mentioned in my question.
Does anybody knows if it is possible to connect to Sql Compact with the Code Only approach? (with a generated .edmx file for a Sql Compact database everthing works fine, but i want to use code only!)
Here is some code:
My Class which is building the DataContext:
public class DataContextBuilder : IDataContextBuilder
{
private readonly DbProviderFactory _factory;
public DataContextBuilder(DbProviderFactory factory)
{
_factory = factory;
}
#region Implementation of IDataContextBuilder
public IDataContext CreateDataContext(string connectionString)
{
var builder = new ContextBuilder<DataContext>();
RegisterConfiguration(builder);
var connection = _factory.CreateConnection();
connection.ConnectionString = connectionString;
var ctx = builder.Create(connection);
return ctx;
}
#endregion
private void RegisterConfiguration(ContextBuilder<DataContext> builder)
{
builder.Configurations.Add(new PersonConfiguration());
}
}
The line
var ctx = builder.Create(connection);
is throwing the exception.
The IDataContext is just a simple Interface for the ObjectContext:
public interface IDataContext
{
int SaveChanges();
IObjectSet<Person> PersonSet { get; }
}
My connection string is configured in the app.config:
<connectionStrings>
<add name="CompactConnection" connectionString="|DataDirectory|\Test.sdf"
providerName="System.Data.SqlServerCe.3.5" />
</connectionStrings>
And the build action is started with
var cn = ConfigurationManager.ConnectionStrings["CompactConnection"];
var factory = DbProviderFactories.GetFactory(cn.ProviderName);
var builder = new DataContextBuilder(factory);
var context = builder.CreateDataContext(cn.ConnectionString);
I have to answer my own question.
This works now with the
Entity Framework CTP 4
and
SQL Server Compact 4.0