C# Entity Framework: Keyword not supported: 'port' - c#

Hello I have more than one project connecting to a certain DB that is CodeFirst Entity Framework.
All Projects are able to connect successfully except for one stubborn one.
The error I am getting is: Keyword not supported: 'port'
I have looked through countless stackoverflow questions, mysql forums, entity framework forums etc. including:
MappingException Edm.String not compatible with SqlServer.varbinary
Keyword not supported in MySQL's connection string
Keyword not supported: 'metadata' + MySQL
My connection string looks like:
server=myservername;port=3306;uid=myaccount;database=mydb;pwd=mypwd123
My db.cs file looks like:
public partial class MyDB : DbContext
{
public MyDB ()
: base("server=myservername;port=3306;uid=myaccount;database=mydb;pwd=mypwd123")
{
Logger.Trace("test123");
}
public virtual DbSet<MyItem> MyItems {
get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyItem>()
.Property(e => e.Content)
.IsUnicode(false);
}
}
When I remove the port:3306 from the connection string I get this:
System.Data.Entity.Core.MappingException: Schema specified is not valid. Errors:
(8,12) : error 2019: Member Mapping specified is not valid. The type 'Edm.DateTime[Nullable=False,DefaultValue=,Precision=]' of member 'Time' in type 'something.Model.MyItem' is not compatible with 'SqlServer.timestamp[Nullable=False,DefaultValue=,MaxLength=8,FixedLength=True,StoreGeneratedPattern=Identity]' of member 'time' in type 'CodeFirstDatabaseSchema.MyItem'.
at System.Data.Entity.Core.Mapping.StorageMappingItemCollection.Init(EdmItemCollection edmCollection, StoreItemCollection storeCollection, IEnumerable`1 xmlReaders, IList`1 filePaths, Boolean throwOnError)
at System.Data.Entity.Core.Mapping.StorageMappingItemCollection..ctor(EdmItemCollection edmCollection, StoreItemCollection storeCollection, IEnumerable`1 xmlReaders)
at System.Data.Entity.ModelConfiguration.Edm.DbDatabaseMappingExtensions.ToStorageMappingItemCollection(DbDatabaseMapping databaseMapping, EdmItemCollection itemCollection, StoreItemCollection storeItemCollection)
at System.Data.Entity.ModelConfiguration.Edm.DbDatabaseMappingExtensions.ToMetadataWorkspace(DbDatabaseMapping databaseMapping)
at System.Data.Entity.Internal.CodeFirstCachedMetadataWorkspace..ctor(DbDatabaseMapping databaseMapping)
at System.Data.Entity.Infrastructure.DbCompiledModel..ctor(DbModel model)
at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
at System.Data.Entity.DbSet`1.Add(TEntity entity)
at MyFunction(Int32 userId, String id, String type, String contentJsonString) in
I am using MySql Connector and not Sql Server...
I am completely stumped by this as well as the rest of my team.
Edit:
Here is my Web.Config
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
</configSections>
<appSettings file="config-sources\app-settings.config"/>
<system.web>
<compilation debug="true" targetFramework="4.5.2">
<assemblies>
<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</assemblies>
</compilation>
<httpRuntime targetFramework="4.5.1"/>
</system.web>
<connectionStrings configSource="config-sources\ef-connection-strings.config"/>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MySql.Data" publicKeyToken="C5687FC88969C44D" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.8.3.0" newVersion="6.8.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-3.3.0.0" newVersion="3.3.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="POST,HEAD,GET" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<security>
<requestFiltering>
<verbs>
<add verb="POST" allowed="true"/>
</verbs>
</requestFiltering>
</security>
<defaultDocument>
<files>
<add value="webhook.ashx"/>
</files>
</defaultDocument>
</system.webServer>
</configuration>

The argument of the used base DbContext constructor is called nameOrConnectionString. Hence it supports a name of a connection string from the configuration file, or like in your case an actual connection string.
The problem with the later is that it doesn't allow specifying the provider name as with the former coming from the configuration, in which case EF uses the one specified in the defaultConnectionFactory configuration element, which in your case is System.Data.Entity.Infrastructure.SqlConnectionFactory, in other words - Sql Server, hence the port not supported exception.
There are several ways to fix the issue.
(A) Change the defaultConnectionFactory configuration:
<defaultConnectionFactory type="MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6"></defaultConnectionFactory>
(B) Use named configuration connection string and specify explicitly the provider:
<connectionStrings>
<add name="MyDB" providerName="MySql.Data.MySqlClient" connectionString="server=myservername;port=3306;uid=myaccount;database=mydb;pwd=mypwd123" />
</connectionStrings>
and change the constructor to
public MyDB()
{
// ...
}
or if the name is different than your DbContext derived class name:
public MyDB() : base(connection_string_name)
{
// ...
}
(C) Use DbConfigurationTypeAttribute:
[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
public class MyDB : DbContext
{
// ...
}

I had this problem whilst developing a Web Application on Core 2. I had to change the default database connection used from SqlServer to MySql in the Startup.cs file where the application is configured.

The error similar to the one listed above comes while working with ASP.net core and Database. The default database Provider with the ASP.net core is the SQL Server but, in case you are using a different provider for example, PostgreSQL and didn't correctly write or configure the DBContext code in the startup.cs
For example - Following code is written with an intent to connect to PostgresSQL then it will result in error ArgumentException: Keyword not supported: 'port'.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
var connection = #"Server=localhost;Port=5432;Database=NewDB;User Id=xxxxx;Password=cr#aaaa;";
services.AddDbContext<BloggingContext>(options => options.UseSqlServer(connection));
// ...
}
And the reasons is user is trying to connect to PostgreSQL but did change the default Option UseSQLServer after configuring the PostgreSQL string.
To fix the issue change the option
options.UseSqlServer(connection)) -> options.UseNpgsql(connection))

I definitively solved the problem using the MySql Connector 8.0.x and following instructions on this link: https://davidsekar.com/asp-net/mysql-error-the-provider-did-not-return-a-providermanifesttoken.
in details:
Install MySql.Data.EntityFramework. Do not install Install MySql.Data.Entity!
Configure web.config / app.config in this way:
2.1. Change the <entityFramework> tag to <entityFramework codeConfigurationType="MySql.Data.EntityFramework.MySqlEFConfiguration, MySql.Data.EntityFramework">
2.2. Add/change the provider. It has to be: <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.EntityFramework" />
2.3. Connection string now can be server=myservername;port=3306;uid=myaccount;database=mydb;pwd=mypwd123
Open your DbContext's configuration class (if presente) and place the following code in it's constructor:
SetSqlGenerator("MySql.Data.MySqlClient" new MySql.Data.EntityFramework.MySqlMigrationSqlGenerator());

In my case, connection string with explicit port has to be delimited by ,.
E.g.: Data Source=123.45.123.45,1433;...

Sometimes it's the simplest thing. Mine was a copy-paste error when I missed the "Server=" at the beginning of the connection string.

Related

passing optional parameter to GET method of ASP.NET API

I am learning ASP.NET API. in the controller I have this methof for GET Verb
public HttpResponseMessage Get(string gender="All")
{
using (EmployeeDBEntities entities = new EmployeeDBEntities())
{
switch(gender.ToLower())
{
case "all":
return Request.CreateResponse(HttpStatusCode.OK, entities.Employees.ToList());
case "female":
case "male":
return Request.CreateResponse(HttpStatusCode.OK,
entities.Employees.Where(x=>x.Gender==gender).ToList());
default:
return Request.CreateErrorResponse(HttpStatusCode.NotFound, " value of gender is wrong");
};
}
}
when I browse to http://localhost:61491/api/Employees/gender=female , I recieve the following error:
<Error>
<Message>The request is invalid.</Message>
<MessageDetail>The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Net.Http.HttpResponseMessage Get(Int32)' in 'EmployeeService.Controllers.EmployeesController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.</MessageDetail>
</Error>
/**Edit
This is the web.config file of API Service
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="EmployeeDBEntities" connectionString="metadata=res://*/EmployeeDataModel.csdl|res://*/EmployeeDataModel.ssdl|res://*/EmployeeDataModel.msl;provider=System.Data.SqlClient;provider connection string="data source=localhost;initial catalog=EmployeeDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
<httpModules>
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
</httpModules>
</system.web>
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<remove name="ApplicationInsightsWebTracking" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
</modules>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" />
</compilers>
</system.codedom>
</configuration>
what could be the reason?
Your code is fine. It's your url that is wrong:
http://localhost:61491/api/Employees/gender=female
I will give a quick solution as to what it should be, then give more details I highly recommend you read if you are learning APIs. Your URL should be:
http://localhost:61491/api/Employees?gender=female
With C# APIs you can send data in 3 possible ways:
Query Parameter
Route Parameter
In the Request Body
Query Parameters
This is the default type. Meaning if you don't specify the method it will always assume your inputs are query parameters. Not only that, but query parameters are by default optional and nullable. If you put in a null for a query parameter it will be assigned the default value.
Query parameters can be identified in a URL by the ? mark. Any data after that are query parameters and can be assigned in any order. For example:
MyUrl?Name=Jhon&Age=20&Sex=M
The & shows it's a split. The data above will map to the endpoint:
public HttpResponseMessage Get(string name, string sex, int age)
The paremeters can be in any order. It will map correctly.
Route Paremeters
These are queries taken directly from route. Adapting your request it will look like this:
/api/Employees/gender/female
And the endpoint itself will look as follow:
[HttpGet("gender/{sex}")]
public HttpResponseMessage Get([FromRoute] string sex) {...}
You can't by default use Route parameters, you will need to specify it is a route parameter by:
Putting the parameter in the route for the end point in brackets {}
Indicate with the [FromRoute] attribute that the api should use the route to get the attribute. By Default the route is required. You cannot use it as an optional parameter.
Body Parameters
This is simply you read the body of the request as a parameter. Good when you are posting or putting data Not going into too much detail but it will look as follow:
public HttpResponseMessage Get([FromBody] Model data) {...}
It is important to note that the [FromBody] parameters aren't compatible with Get requests.
Request Types
One important thing you will need to know is the request types. There are many but by default it will always be a Get request.
Your code:
public HttpResponseMessage Get(...) {...}
Is not a get reqest because you wrote GET. You can name that request whatever you like such as:
public HttpResponseMessage ThisIsMyPostRequest(...) {...}
But you will still be able to retrieve data using a GET request. The Specify what type of requests it is, you can add a http attribute tag:
[HttpGet]
public HttpResponseMessage MyGetFuncName(){...}
[HttpPost]
public HttpResponseMessage MyPostFuncName(){...}
[HttpPut]
public HttpResponseMessage MyPutFuncName(){...}
[HttpDelete]
public HttpResponseMessage MyDeleteFuncName(){...}
[HttpOptions]
public HttpResponseMessage MyOptionsFuncName(){...}
[HttpHead]
public HttpResponseMessage MyHeadFuncName(){...}
...
It is really that easy. The different HttpRequest mostly work the same. But there are a few differences. The most common used are GET, POST, PUT and DELETE.
This becomes usefull when say you want to use the same route but different functions. For example GET and DELETE can be on the same route:
/api/Employees/Byname?name=Jhon
but depending on the request type will either return the user or delete it.
Custom Routes
The last important and powerfull thing you will need to know is Routes. If I am not mistaken at the top of your controller page you have the following attribute:
[Route("[controller]")]
or
[Route("api/[controller]")]
What that function does is it ands a prefix to all of the requests on the controller. Now you can actually add this to individual functions as well. Meaning if you have multiple GET functions on a single page, this will be essential to keep it working properly. Example:
[Route("ByGenders")]
public HttpResponseMessage Get(string gender="All")
/api/Employees/ByGenders?gender=female
...
[Route("Byname")]
public HttpResponseMessage Get(string name)
/api/Employees/Byname?name=Jhon
But it can actually be combined with the HttpRequest attributes. Meaning the above will be equivalent to:
[HttpGet("ByGenders")]
public HttpResponseMessage Get(string gender="All")
[HttpGet("Byname")]
public HttpResponseMessage Get(string name)
Ofcourse you can put all of the above together into a unique endpoint with a lot of details. Below is a small example:
[HttpGet("GetWithParams/{requiredInput}")]
public IActionResult GetWithParams(
[FromRoute] string requiredInput,
[FromQuery] string optionalInput)
{
return Ok($"Required Input: {requiredInput} | Optional Input: {optionalInput}");
}
Or
[HttpPost("UserId/{id}")]
public IActionResult SubmitApplication(
[FromRoute] int id,
[FromBody] UserApplicationModel application)
{
return BadRequest();
}

How to Pass Full Sqlite Connection String to DbContext

I am trying to pass the full connection string to DbContext constructor as an argument and I get this error:
Unable to complete operation. The supplied SqlConnection does not specify an initial catalog or AttachDBFileName.
And this is what I have tried:
public DatabaseContext() :base(#"Data Source=|DataDirectory|ComponentDatabase.sqlite") {}
Problem can't be about anything else but connection string because I was able to connect my database using connection string from App.config like this:
App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<entityFramework>
<providers>
<provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
</providers>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
</entityFramework>
<connectionStrings>
<!-- use AppDomain.SetData to set the DataDirectory -->
<add name="MapDbConnectionStr" connectionString="Data Source=|DataDirectory|ComponentDatabase.sqlite" providerName="System.Data.SQLite" />
</connectionStrings>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SQLite.EF6" />
<add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
<remove invariant="System.Data.SQLite" /><add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /></DbProviderFactories>
</system.data>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite" publicKeyToken="db937bc2d44ff139" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.105.2" newVersion="1.0.105.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Data.SQLite.EF6" publicKeyToken="db937bc2d44ff139" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.105.2" newVersion="1.0.105.2" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
DbContext
public DatabaseContext() :base("MapDbConnectionStr") {}
P.S. I know that App.config has a lot of unnecessary lines, yes.
As far as I am aware there isn't a Connection factory for the type of database you are trying to connect to.
You could write your own connection factory:
public class MySqlLiteConnectionFactory : IDbConnectionFactory
{
public DbConnection CreateConnection(string connectionString)
{
return new SQLiteConnection(connectionString);
}
}
now go and find the entry for defaulConnectionfactory in app.config and replace the line which specifies the type. At the moment thats going to read something like this:
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
change it to something like this:
<defaultConnectionFactory type="MyNamespace.MySQLiteConnectionFactory, MyAssemblyHere" />
You should now be able to correctly use the Context ctor (string connectionString).
There is another was of doing this without relying on appsettings EF 6 and onwards supports code-based configuration.
So you can do something with configurations that looks a bit like this:
DbConfiguration.Loaded += (_, a) =>
{
a.ReplaceService<DbProviderServices>((s, k) => new MyProviderServices(s));
a.ReplaceService<IDbConnectionFactory>((s, k) => new MyConnectionFactory(s));
};
Full details of this are documented here at microsoft:
Using the name from config file works because it can determine the provider type based on accompanying config provided. When using the connection string directly in the constructor it cannot determine that the connection string is for SQLite and assumes MSSQL so it is trying to use a SqlConnection. Hence the error message you encountered.
Take Note:
The connection to the database (including the name of the database)
can be specified in several ways. If the parameterless DbContext
constructor is called from a derived context, then the name of the
derived context is used to find a connection string in the app.config
or web.config file. If no connection string is found, then the name is
passed to the DefaultConnectionFactory registered on the Database
class. The connection factory then uses the context name as the
database name in a default connection string. (This default connection
string points to .\SQLEXPRESS on the local machine unless a different
DefaultConnectionFactory is registered.) Instead of using the derived
context name, the connection/database name can also be specified
explicitly by passing the name to one of the DbContext constructors
that takes a string. The name can also be passed in the form
"name=myname", in which case the name must be found in the config file
or an exception will be thrown. Note that the connection found in the
app.config or web.config file can be a normal database connection
string (not a special Entity Framework connection string) in which
case the DbContext will use Code First. However, if the connection
found in the config file is a special Entity Framework connection
string, then the DbContext will use Database/Model First and the model
specified in the connection string will be used. An existing or
explicitly created DbConnection can also be used instead of the
database/connection name.
Taken from the class remarks for DbContext
The last quoted sentence stands out...
An existing or explicitly created DbConnection can also be used
instead of the database/connection name.
You could consider using SQLiteConnection
public class DatabaseContext : DbContext {
public DatabaseContext()
:base(new SQLiteConnection(#"Data Source=|DataDirectory|ComponentDatabase.sqlite"), true) {
//...
}
//...
}
As i understood correctly it could be helpful, please use builder with db context options. I use SqlServer, hovewer there should be not a lot of changes.
var builder = new DbContextOptionsBuilder<MapDbContext>();
builder.UseSqlServer(ConfigurationManager.ConnectionStrings["MapDbConnectionStr"].ConnectionString), opt => opt.EnableRetryOnFailure());
var mycontext = new MapDbContext(builder.Options);
public MapDbContext(DbContextOptions<MapDbContext> options)
: base(options)
{ }
Hope it helps, Good luck.

Entity SetInitializer gets an SQL timeout

Using Entity's visual designer I have created the most basic entity possible. I want to seed some sample data to a database I created which holds the schema for this basic entity on Azure. I want to use this db in an asp.net web form but when I go to seed the init data I get an SQL timeout error.
I am aware that when using entities Database.SetInitializer the seed operation is only called when the context is used so I forced the initialization. It seems to try yet I still get the timeout. I created a basic console application and wrote a test program to load some values into the table and it worked fine so I know it is not the connection to the DB, it is something to do with the Seeding.
Here is the actual error:
A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in EntityFramework.SqlServer.dll
An exception of type 'System.Data.SqlClient.SqlException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
Context File
namespace SlowTest.DB
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class ModelContainer : DbContext
{
public ModelContainer()
: base("name=ModelContainer")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Books> Books { get; set; }
}
}
Entity Class
namespace SlowTest.DB
{
using System;
using System.Collections.Generic;
public partial class Books
{
public int BookId { get; set; }
public string Author { get; set; }
}
}
Initializer
namespace SlowTest.DB
{
public class Init : DropCreateDatabaseAlways<ModelContainer>
{
protected override void Seed(ModelContainer context)
{
GetBooks().ForEach(c => context.Books.Add(c));
}
private static List<Books> GetBooks()
{
var B = new List<Books>
{
new Books{
BookId = 0,
Author = "Neville",
},
new Books{
BookId = 3,
Author = "Steve",
},
};
return B;
}
}
}
Global.asax.cs
namespace SlowTest
{
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Database.SetInitializer<ModelContainer>(new Init());
ModelContainer db = new ModelContainer();
db.Database.Initialize(true);
}
}
}
EDIT
Here is my web.config. Most of which is auto generated by visual studio or entity
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-SlowTest-20150812115338.mdf;Initial Catalog=aspnet-SlowTest-20150812115338;Integrated Security=True" providerName="System.Data.SqlClient" />
<add name="ModelContainer" connectionString="metadata=res://*/DB.Model.csdl|res://*/DB.Model.ssdl|res://*/DB.Model.msl;provider=System.Data.SqlClient;provider connection string="data source=uvic.database.windows.net;initial catalog=TrojanDB;persist security info=True;user id=nhoughto;password=Password;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<pages>
<namespaces>
<add namespace="System.Web.Optimization" />
<add namespace="Microsoft.AspNet.Identity" />
</namespaces>
<controls>
<add assembly="Microsoft.AspNet.Web.Optimization.WebForms" namespace="Microsoft.AspNet.Web.Optimization.WebForms" tagPrefix="webopt" />
</controls>
</pages>
<membership>
<providers>
<!--
ASP.NET Membership is disabled in this template. Please visit the following link http://go.microsoft.com/fwlink/?LinkId=301889 to learn about the ASP.NET Membership support in this template
-->
<clear />
</providers>
</membership>
<profile>
<providers>
<!--
ASP.NET Membership Profile is disabled in this template. Please visit the following link http://go.microsoft.com/fwlink/?LinkId=301889 to learn about the ASP.NET Membership support in this template
-->
<clear />
</providers>
</profile>
<roleManager>
<!--
ASP.NET Membership Role is disabled in this template. Please visit the following link http://go.microsoft.com/fwlink/?LinkId=301889 to learn about the ASP.NET Membership support in this template
-->
<providers>
<clear />
</providers>
</roleManager>
<!--
If you are deploying to a cloud environment that has multiple web server instances,
you should change session state mode from "InProc" to "Custom". In addition,
change the connection string named "DefaultConnection" to connect to an instance
of SQL Server (including SQL Azure and SQL Compact) instead of to SQL Server Express.
-->
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" />
</providers>
</sessionState>
</system.web>
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
</modules>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" culture="neutral" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" culture="neutral" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" culture="neutral" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" culture="neutral" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" culture="neutral" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
I know this is an old question, but in case anyone stumbles here from Google... you need to increase your CommandTimeout to give Azure enough time to create the db.
There is an incredibly detailed StackOverlow answer explaining why here:
Timeout when setting up Entity Framework connecting to Azure
The gist of it is that you need to add a single line into your DbContext constructor:
public MyContext() : base("name=MyContext")
{
// three minute command timeout
this.Database.CommandTimeout = 180;
}

Inserting a new record updates LocalDB but not SQL server DB

I'm following MVC-Movies tutorial here , and I'm trying to update the records on SQL Server
and NOT on LocalDB .
When I add a new record in my program , for example :
The DB in SQL Server is not updated , only the LocalDB is .
Here is Web.config :
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=301880
-->
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="DefaultConnection"
connectionString="Data Source=localhost;
AttachDbFilename=|DataDirectory|\aspnet-MvcMovie-20140418101450.mdf;
Initial Catalog=aspnet-MvcMovie-20140418101450;Integrated Security=True"
providerName="System.Data.SqlClient" />
<add name="MovieDBContext"
connectionString="Data Source=(LocalDB)\v11.0;
AttachDbFilename=|DataDirectory|\Movies.mdf;
Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.webServer>
<modules>
<remove name="FormsAuthenticationModule" />
</modules>
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
Where did I go wrong ?
Name of my DB in sql server is : MoviesDB
Thanks
EDIT:
Class Movie and MovieDBContext :
using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
namespace MvcMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
public class MovieDBContext : DbContext
{
public DbSet<Movie> Movies { get; set; }
}
}
EDIT 2 :
I changed the connection string to
<add name="MovieDBContext"
connectionString="Data Source=localhost;
AttachDbFilename=|DataDirectory|\Movies.mdf;
Initial Catalog=MoviesDB;
Integrated Security=True"
providerName="System.Data.SqlClient" />
But then I get this :
Server Error in '/' Application.
Invalid value for key 'attachdbfilename'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: Invalid value for key 'attachdbfilename'.
Source Error:
Line 18: public ActionResult Index()
Line 19: {
Line 20: return View(db.Movies.ToList());
Line 21: }
Line 22:
Source File: c:\Users\X3\Documents\Visual Studio 2013\Projects\MvcMovie\MvcMovie\Controllers\MoviesController.cs Line: 20
Neither one of your connection strings there are referencing MoviesDB.
One is referring to aspnet-MvcMovie-20140418101450.mdf and the other Movies.mdf.
Your context will use the connection string that matches it's name, unless you override that setting. So you should modify the MovieDBContext connection string to point to your SQL instance instead of the LocalDB
Edit
I assume that this is similar to the connection string you actually want, but you should refer to the official Microsoft Reference for other examples.
<add name="MovieDBContext" providerName="System.Data.SqlClient"
connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=MoviesDB;
Integrated Security=True"/>
Change to :
<add name="MovieDBContext"
connectionString="Data Source=localhost;
AttachDbFilename=|DataDirectory|\MoviesDB.mdf;
Initial Catalog=MoviesDB;
Integrated Security=True"
providerName="System.Data.SqlClient" />

Error after updgrading from EF 5 to EF 6.0.2

After upgrading from EF 5 to EF 6.0.2 I'm getting this error when executing the Update-Database command from the Package Manager Console:
Could not load file or assembly 'System.Web.Helpers, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its
dependencies. The system cannot find the file specified.
Everything worked just fine before the upgrade.
This is my app.config:
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog=aspnet-CodeFirst-Test;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<roleManager enabled="true" defaultProvider="SimpleRoleProvider">
<providers>
<clear />
<add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData" />
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear />
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
</system.web>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<qualifyAssembly partialName="WebMatrix.WebData" fullName="WebMatrix.WebData, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
</startup>
This is my Configuration.cs file:
public Configuration()
{
Database.SetInitializer<DataContext>(new DropCreateDatabaseAlways<DataContext>());
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(DataContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
SeedMembership(context);
}
I read that SimpleMembershipProvider got 'replaced' with Identity. Not sure if that is related to this error. But if anyone knows a tutorial how to do the migration, I'd love to have a link of that.
Also the database layer is a class lib project. There is no MVC installed in there.
Try adding this to your web.config under runtime section:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
And System.Web.Helpers should be referenced from your project as well

Categories