Entity Framework DBContext Dynamic connection string - c#

I have an application using Entity Framework 6.
I have project named Data where I have my DbContext.
public partial class MyDbContext: DbContext
{
static MyDbContext()
{
Database.SetInitializer<MyDbContext>(null);
}
public MyDbContext()
: base("Name=" + Utility.Constants.DbConnectionName)
{
Database.SetInitializer<MyDbContext>(null);
}
}
Where Utility.Constants.DbConnectionName = "TestConnection"
In my web.config of course I have:
<add name="TestConnection" connectionString="Data Source=MYSERVERIPADDRESS;Initial Catalog=unitdb;User ID=sa;Password=12345;Connect Timeout=600;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
Then I also have a project that is a Windows Service.
Inside that project I have a reference to my Data project so I have a access to my Entity Framework entities. Also in my Windows service project I have an App.config with the same connection string (above) because If not then it won't know where to get the data.
Is there I way I can set inside my Windows service project a connection string dynamically? Because my windows service may connect to a different database (of course that database has the same structure so EF can get the info).

Related

The entity type ApplicationUser is not part of the model for the current context when querying Identity table database

My project is set up as follows..
MainProject
DataAccess its a Class Library
EntityFramework Database tables its a Class Library
EntityFramework Identity tables its a Class Library
In my main projects webconfig I have 2 connectionstrings, one is for the normal database tables and the other is for the Identity tables. The connectionstring for the normal database tables is an entity framework connectionstring
<add name="HWCEntities" connectionString="metadata=res://*/HWCEF.csdl|res://*/HWCEF.ssdl|res://*/HWCEF.msl;provider=System.Data.SqlClient;provider connection string="data source=****;initial catalog=****;persist security info=True;user id=****;password=****;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient"/>
The identity entityframework connectionstring is this
<add name="HWCIdentityEntities" connectionString="metadata=res://*/HWCIdentityEF.csdl|res://*/HWCIdentityEF.ssdl|res://*/HWCIdentityEF.msl;provider=System.Data.SqlClient;provider connection string="data source=****;initial catalog=****;persist security info=True;user id=****;password=****;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
however if I place that connectionstring in the main project's webconfig, and try to log into the web app, I get this error
The entity type ApplicationUser is not part of the model for the current context.
and its pointing at line 78 of AccountController
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
So instead of using the Identity connectionstring, I use this one
<add name="HWCIdentityEntities" connectionString="Data Source=****;Initial Catalog=****;User ID=****;password=****;Integrated Security=false;" providerName="System.Data.SqlClient"/>
using that connectionstring doesn't throw any error, and I would be fine with using that connectionstring but when I try and query the Identity database, I get this error
An exception of type 'System.Data.Entity.Infrastructure.UnintentionalCodeFirstException' occurred in HWC.Identity.dll but was not handled in user code
Additional information: The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection. To learn more about Code First, Database First, and Model First see the Entity Framework documentation here: http://go.microsoft.com/fwlink/?LinkId=394715
and this error is thrown in my HWCIdentityEF.Context.csdl|res
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
How can I fix this so I can query the Identity database? I am assuming that I need to use the Identity connectionstring in the main application?
This works for me:
1) Make sure your context looks similar:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("myConnectString", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
2) Should be only 1 connect string in web.config
3) Tell Identity to use that context instead of IdentityDbContext. Search for IdentityDbContext and replace it with ApplicationDbContext (or whatever you called it). For example:
A) Startup.cs: app.CreatePerOwinContext<ApplicationDbContext>((options, context)=>new ApplicationDbContext());
B) IndentityConfig.cs (user manager and role manager): var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
var manager = new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
After reading solution after solution, and thanks to Steve Greene, I finally figured out what the issue was. I had to change the name of one of the connectionstrings, and changed its context. Now I can login and my queries run.

Pointing a Code First Entity Framework to a created database

I am creating a Code First Entity Framework to create a database to where I point it to. I have an instance of SQL => DESKTOP-98TG6JE\SQLEXPRESS and another one => DESKTOP-98TG6JE
In my Asp MVC code, my connection string is like so in the Web.config
<connectionStrings>
<add name="MusicStoreDB" connectionString="Data Source=DESKTOP-98TG6JE;Initial Catalog=MusicStoreDB;User ID=sa;Password=myPassword123" providerName="System.Data.SqlClient" />
</connectionStrings>
and in my MusicStoreDB : DbContext,
public MusicStoreDB() : base("MusicStoreDB")
{
}
But when I run the program, it creates a database in the DESKTOP-98TG6JE\SQLEXPRESS named DefaultConnection and on the instance where I want to create the database, no MusicStoreDB database is created.
Image of the created database on the wrong instance
Can you please explain it to me why this is happening? Thank you.
Check you connection string name provided in ApplicationDbContext :
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("MusicStoreDB")
{
}
}

ASP.NET Identity MVC 5 working locally but throws ApplicationUser error after switch to external database

I've been following this Microsoft Article on implementing a secure web app. It is working fine with the local database. But when I change the connection string to the external database I consistently get an error when trying to interact with the identity tables
AspNetUsers
AspNetRoles
AspNetUserClaims
AspNetUserLogins
AspNetUserRoles
These tables have been re-created in the external Azure db and I followed this walkthrough. The error I get when trying to register is
The entity type ApplicationUser is not part of the model for the current context.
When trying to register it fails on this line of code in the AccountController
var user = await UserManager.FindByNameAsync(model.Email);
I want to take a database first approach as the external db already has pre-existing data. I've looked at several other posts and sites but I've been unable to solve the issue. I've also tried enabling and updating the db with no success through the Package Manager Console.
Thank you in advance!
Here is the ApplicationDbContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
//ApplicationDbContext.Equals("", "");
return new ApplicationDbContext();
}
public System.Data.Entity.DbSet<proj.Models.Obj1> Obj3 { get; set; }
public System.Data.Entity.DbSet<proj.Models.Obj2> Obj3 { get; set; }
public System.Data.Entity.DbSet<proj.Models.Obj3> Obj3 { get; set; }
}
I don't like answering my own question but here is what resolved my problem.
I had to change the connection string from the one that was generated
<add name="DefaultConnection" connectionString="metadata=res://*/Models.DBName.csdl|res://*/Models.DBName.ssdl|res://*/Models.DBName.msl;provider=System.Data.SqlClient;provider connection string="data source=server;initial catalog=databaseName;user id=username;password=password;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
to this
<add name="DefaultConnection" connectionString="Data Source=server; Initial Catalog=databaseName; User ID=username; Password=password; Connect Timeout=60;" providerName="System.Data.SqlClient" />
I was using the connection string generated during the creation of the EDMX file, database first. Using this connection string was causing my error. I found it a bit deceiving because I was still able to access data from other tables but not the associated identity tables. I hope this will be helpful to anyone experiencing the same issue in the future.

Entity Framework Core use windows service

Currently in the process of building a multi tired application using EF Core for my data access layer and I feel like I'm running in to a problem and I'm not 100% certain I can use it at the moment.
Essentially I'm designing my application into the following components
windows assembly
asp.net mvc core web app
windows service x2
unit test
in good design I'm putting as much of my domain in my assembly so that I can reuse it as much as possible, but this is where I'm running into issues. I'm currently unable to use EF in my unit test app.
I am currently overriding OnConfiguring to set the database connection string but when I attempt to use the context in a unit testI continually get the following exception message: "Instance failure"
My context is dirt simple right now and only has one entity and looks as follows:
public partial class CdiContext : DbContext
{
private string ConnectionString { get; set; }
private bool IsService { get; set; }
public CdiContext(string connectionString, bool isService)
{
ConnectionString = connectionString;
IsService = isService;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConnectionString);
}
public DbSet<Region> Regions { get; set; }
}
In an effort to rule out the unit test as the problem I've also created a simple console application and even it throws the same exception so I'm really lost as to how to proceed.
CdiContext context = new CdiContext(#"Data Source=localhost\\SQLEXPRESS;Initial Catalog=herp-interface;Persist Security Info=True;User ID=sa;Password=herpaderp;Pooling=true", true);
var regions = context.Regions.ToList();
Console.ReadLine();
The question is what am I doing that's wrong where I am unable to use a EF context from a windows assembly in any type of project aside from an ASP.NET Core MVC app?
This error - "Instance failure" - occurs when you copy/paste the connection string from your aspnetcore app, and still have escaped backslashes.
Outside of ASP.Net Core, ie a console/windows service etc, the connection string in the app.config does not need to escape the backslashes.
EG
<add name="DefaultConnection" connectionString="Server=localhost\\SQLEXPRESS...
rather then
<add name="DefaultConnection" connectionString="Server=localhost\SQLEXPRESS...

C# Setting Entity Framework connectionstring in controller

I'm build my webapi project based on this article: A simple POC using ASP.NET Web API, Entity Framework, Autofac, Cross Domain Support
However, I need to pass a connection string to the DbContext because a user that connects to the webapi can select a different database to work with.
Where and what is that best way to implement this? In the controller, having a separate 'service' or a singleton?
I'm currently building a website that requires multiple databases also. This is the basics (for now). It may not be the best/efficient way, but it does the job so that I can continue working on the site.
Let's say you have this connection and everything there is correct, except the database name can change.
<add name="MyDbContext" connectionString="Server=SomeConnection;Database=SomeDatabase;"providerName="System.Data.SqlClient" />
You can create a connection string on the fly with this
public MyDbContext CreateDbContext(string databaseName)
{
SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder(System.Configuration.ConfigurationManager.ConnectionStrings["MyDbContext"].ConnectionString); // Gets the default connection
sqlBuilder.InitialCatalog = databaseName; // Update the database name
return new MyDbContext(sqlBuilder.ToString());
}
Also, unless you want to automatically create a database if it doesn't exist, possibly from incorrect database name, you need to set the initializer. Simply pass the initializer null to prevent ef from automatically creating one. I set this in the constructor of MyDbContext
public class MyDbContext : DbContext
{
/* some other constructors */
public MyDbContext(string nameOrConnectionString, bool createDb)
: base(nameOrConnectionString)
{
if(!createdDb)
{
System.Data.Entity.Database.SetInitializer<MyDbContext>(null);
}
}
}
One way would be to have multiple ConnectionStrings in your web config. You could then select which ConnectionString to use depending on a parameter passed to your webapi:
In your web config:
<connectionStrings>
<add name="dataBase1" connectionString="/*db info here*/" providerName="System.Data.SqlClient" />
<add name="dataBase2" connectionString="/*db info here*/" providerName="System.Data.SqlClient" />
</connectionStrings>
Then in your code:
public someobject GetData(/*arguments*/, string dbType)
{
var connectionString = dbType == 'dataBase1'
? ConfigurationManager.ConnectionString['dataBase1'].toString()
: ConfigurationManager.ConnectionString['dataBase2'].toString()
/*then pass connectionString to dbContext*/
var dbContext = new DbContext(connectionString);
}

Categories

Resources