Merge MyDbContext to Asp.net IdentityDbContext - c#

I saw a lot of examples online but none that I could use from top to bottom about merging my own DbContext with Asp.net IdentityDbContext.
Can someone please walk me through it? I am at step 0, and what I want is to have the tables generated by ASP.net IdentityDbContext inside my own database, so that I can retain user data in my own database. How can I achieve that?
Thanx in advance :)

If I got you correct, you are trying to use your existing database, tables and existing users with asp.net identity framework.
First thing, according to my understanding, you can't merge your db context (MyDbContext) with 'IdentityDbContext', because context of asp.net identity framework tables has to be inherited from IdentityDbContext<YourUserTable>. But your other tables may inherited from DbContext.
Therefore you have to use two separate db contexts if you want to use identity framework build in method support, which is UserManager etc.
You can use your existing database with identity framework, you just need to correctly bind your database tables with identity framework EF code first approach using model binding.
There is a YouTube video tutorial which may help you to get some idea in order to achieve your task. Actually this video illustrates to use Identity 2.0 with existing database.
Part 1: https://www.youtube.com/watch?v=elfqejow5hM
Part 2: https://www.youtube.com/watch?v=JbSqi3Amatw
Hope this helps.

I'm not really sure what you're trying to achieve but check this question to see if it's of any help.
ASP.NET Identity DbContext confusion

Here's part of a walk-through I created. There are a few steps included specific to making it work with code first migrations but you should be able to accomplish what you want using these steps.
Start by creating a new ASP.NET MVC project. Call it Contacts if you want the included code to match. The authentication defaults to Individual User Accounts which is what we want in this case. Deselect Host in the Cloud for now. You can enter your publishing settings later. Once the project is created bring up the Package Manager Console and Install-Package EntityFramework. Now since we are doing Code First add a simple model class.
public class Contact {
public int ContactID { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
}
At this point you would usually add controllers and such but since this post is focusing on the data side of things we'll skip over all of that. Next we want to add our database context. Go ahead and add it right in the Models namespace.
public class ContactContext : IdentityDbContext {
public ContactContext()
: base("ContactContext") {
}
public DbSet<Contact> Contacts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public static ContactContext Create() {
return new ContactContext();
}
}
A couple of things to note here. Since we're consolidating the Identity tables into our application's context we want to inherit from IdentityDbContext instead of just DbContext. Also, I prefer not to use the generated "DefaultConnection" that gets created in Web.config so I'm passing "ContactContext" as the connection string name to the base constructor. We'll modify the connection string in a minute. If you're typing in the OnModelCreating method Visual Studio should add the call to base.OnModelCreating but if not make sure you add it since it's essential for building the identity tables. Although not essential, you can configure the modelBuilder not to pluralize table names. Add a Create method which is needed for the Identity code to use this context. Also, as you add code you'll need to right-click and Resolve to add the appropriate using statements.
As promised, here is the modified connection string to be updated in the web.config in the root of the site. The name property is changed to something that makes sense for the application and the AttachDbFilename and Initial Catalog values are changed to something a little more user friendly than the auto generated name.
<add name="ContactContext" connectionString="Data Source=
(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\ContactContext.mdf;Initial
Catalog=ContactContext;Integrated Security=True"
providerName="System.Data.SqlClient" />
Now go to the Models folder and open the IdentityModels.cs file. Cut the ApplicationUser class from here and paste it into your Contact.cs file. Again you'll have to resolve a few missing namespaces. At this point you can safely delete the IdentityModels.cs file. Since we've eliminated the ApplicationDbContext we'll need to do a find on ApplicationDbContext and replace it with ContactContext in a few places. You should be able to do a clean build.

Related

Entity Framework 6 Migrations with views

I need to map to a view when using EF6 with migrations.
The view pivots 2 other tables to enable a simple summary view of the underlying data, the idea being it allows us to use this in a summary index view.
The issue I have is I am unable create a migration that either deploys the view (ideal goal) or deploys the DB without the view for later manual deployment.
In most attempts, following other SO questions, I end up either deadlocking the Add-Migration and Update-Database commands or generally causing an error that breaks one or the other.
What is the current best way to use EF6 to access views, even if I lose the ability to automatically deploy them with the migrations, and not cause errors with migrations.
Further detail
The Db contains 2 tables Reports and ReportAnswers. The view ReportView combines these two and pivots ReportAnswers to allow some of the rows to become columns in this summary view.
Reports and ReportAnswers were depolied via EF Migrations. The view is currently a script that needs be added to the deployment somehow.
Reports, ReportAnswers & ReportView are accessible from the db Context
public virtual DbSet<ReportAnswer> ReportAnswers { get; set; }
public virtual DbSet<Report> Reports { get; set; }
public virtual DbSet<ReportView> ReportView { get; set; }
I have tried using Add-Migration Name -IgnoreChanges to create a blank migration and then manually adding the view to the Up() and Down() methods but this just deadlocks the migration and update commands, each wanting the other to run first.
I have also tried using modelBuilder.Ignore<ReportView>(); to ignore the type when running the migrations but this proved incredibly error prone, even though it did seem to work at least once.
I just walked around interesting article about using views with EF Core few days ago, but I found also the very same using EF 6.
You may want to use Seed method instead of migration Up and Down methods.
protected override void Seed({DbContextType} context)
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
var baseDir = Path.GetDirectoryName(path) + "\\Migrations\\{CreateViewSQLScriptFilename}.sql";
context.Database.ExecuteSqlCommand(File.ReadAllText(baseDir));
}
Your SQL command should look like sample below.
IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'[dbo].[{ViewName}]'))
EXEC dbo.sp_executesql #statement = N'CREATE VIEW [dbo].[{ViewName}]
AS
SELECT {SelectCommand}
It is not perfect, but I hope at least helpful.
I found another blog post about this topic and the writer says to use Sql(#"CREATE VIEW dbo.{ViewName} AS...") in Up method and Sql(#"DROP VIEW dbo.{ViewName};") in Down method. I added it as you didn't supplied the code from Up and Down migration methods. Maybe good idea will be to add SqlFile instead of Sql method.
There is also option to create customized code or sql generator and plug it in to migrations, but I guess it is not the things you are looking for.
Let me know in comment in case you need additional help.
Related links:
Using Views with Entity Framework Code First
EF CODE FIRST - VIEWS AND STORED PROCEDURES
Leveraging Views in Entity Framework
DbMigration.Sql Method (String, Boolean, Object)
DbMigration.SqlFile Method (String, Boolean, Object)

Entity Framework returns every table from Azure DB instead of one

I'm building a Web Api using ASP.NET and an existing Azure DB. I'm running into an issue with entity framework and the Azure DB. I've used ADO.NET to generate all of the model classes from the database with the code-first version..
This is a snippet of my dbcontext that was generated with ADO.NET:
public IntelliMonDbContext()
: base("name=IntelliMonDbContext")
{
}
public virtual DbSet<C__MigrationHistory> C__MigrationHistory { get; set; }
public virtual DbSet<Device> Devices { get; set; }
After all of the dbset properties there is a method called OnModelCreating. I'm not really sure what that one does but since it was generated I don't think this is where my method lies.
My problem is, that in my DevicesController I'm trying to return a list of all of my devices in JSON-format, but instead it returns all of the tables in my Azure DB. I've tried trying to query for other tables in the db instead of Devices, but I get the exact same result. Even when I try requesting with a specific device-id I get all of the tables in one JSON-object.
// GET: api/Devices
public IEnumerable<Device> GetDevices()
{
return db.Devices.ToList();
}
I've worked with lokal Db's and entity-framework before and I have never had any issues. I don't understand how the query above can give me all of the tables in the DB in one JSON-object. Have I missed a cruicial step when generating the models using ADO.NET? What might be the issue here? I've tried my best searching for similar posts but I can't find anything that matches, since this feels like it's such a simple thing that should not go wrong.
If it's needed I'll provide more information.
Turns out it was the ICollections inside of the objects that was doing this. I only removed virtual from the properties as suggested by another user, but I missed the ICollections that was auto generated by ADO.NET.
Thank you for the help.

Bind database to Collection c#

I am developing a data intensive app in C# and need some advice on the best method to manage my data. My application will use a number of related tables with a lot of movement backwards and forwards between the app and the database.
My question is, what method would be best to handle data? All of my data fields are controlled within their own classes and collections, so hence, the question is really more of a case of what is the best method to bind my collections and objects to the database.
Should I manually create my own SQL connections / SQL Insert / Update queries, or is there another way to do this? For instance is it possible in Visual Studio to easily create a strongly typed data layer that will automatically look after Inserts / Updates / Deletes etc?
Many thanks
Q. For instance is it possible in Visual Studio to easily create a strongly typed data layer that will automatically look after Inserts / Updates / Deletes etc?
Entity Framework sounds like something you're looking for. There is, of course, some setup involved. With most web projects, Entity Framework is automatically added, and if not you can always add it via NuGet package manager.
EntityFramework binds your models to a Database through the DbContext object, and Code First will even generate a database if one does not exist based on your models (if one does exist and the models change, you might have to migrate: More reading). I will be taking that approach (you can later change the following code to a connection string to a live DB).
First, you need to tell your application what database to use (whether it exists or not), and this can be done in the Web.Config file (not the only approach).
Web.Config
<configuration>
....
<connectionStrings>
<add name="ConnectionStringName" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\DATABASENAME.mdf;Initial Catalog=DATABASENAME;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
NOTE - this connection string will only work in VS2015. For previous versions, use:
Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\DATABASENAME.mdf
More reading on configuring Entity Framework
Now, we can use "ConnectionStringName" to connect our context.
The Context class will have to inherit from the DbContext object, and we will pass this connection string name to the base constructor (DbContext exists in the System.Data.Entity namespace). I will use two generic models that look identical (ModelA ModelB) --
ModelA and ModelB
using System.ComponentModels.DataAnnotations;
public class ModelA
{
public int Id { get; set; }
[Required(ErrorMessage="You need to enter a name!")]
[StringLength(40)]
public string Name { get; set; }
}
NOTE - I'm using DataAnnotations (Required, StringLength) - these are really cool and can be very useful when implementing CRUD operations on your model.
ALSO -- Entity Framework will automatically make properties that are named: Id (or any case form) or ModelNameId the primary key. There are ways to override this.
More reading on DataAnnotations
You can even create your models with relationships in mind. If ModelA will have a one-to-many relationship with ModelB, you can reflect this relationship in code:
public virtual ICollection<ModelB> ModelBs {get; set;}
More reading on creating relationships
We will now map your models to tables using the DbSet collection. Here's how that looks:
using System.Data.Entity;
using YourProject.Data.Models;
namespace YourProject.Data.DAL
{
public class YourContext : DbContext
{
public YourContext() : base("ConnectionStringName")
{
}
public DbSet<ModelA> ModelAs { get; set; }
public DbSet<ModelB> ModelBs { get; set; }
}
}
Database Initialization Strategies - for seeding your database with data on creation.
More reading on configuring the context
I will never be able to detail everything you can do - but here are a few short examples:
Q. What does all this do?
You now have a strongly-typed object connected to your database. It's as simple as creating a new Context object:
YourContext yourContext = new YourContext();
Retrieving a whole table is as easy as:
IEnumerable<ModelA> modelAs = yourContext.ModelAs;
or finding a row by Id
ModelB modelB = yourContext.ModelBs.Find(id);
Say you grabbed modelB and want to update it. It's as easy as:
modelB.Name = "Here's the new name";
yourContext.Entry(modelB).State = EntityState.Modified;
yourContext.SaveChanges();
Adding:
yourContext.ModelAs.Add(newModel);
Removing:
yourContext.ModelBs.Remove(modelB);
REMEMBER Add/Update/Delete methods will ALL require a call to SaveChanges(); from the Context. Otherwise they will be discarded.
Of course, this is probably the most basic rundown of Entity Framework available. To see more of it in action check out these tutorials:
WebForms with Entity Framework - Wingtip Toys
MVC with Entity Framework - Contoso University
Hope this may be of assistance for someone.

I want to use Entity Framework + ASP Identity but I don't want EF to generate tables for me

I have created new ASP MVC 5 app (with asp identity).
I use IdentityDbContext class to put all my domain objects inside.
public class SecurityContext : IdentityDbContext{
...
public DbSet<Country> Countries { get; set; }
When I first time created user all database tables were created (identity tables) including my Country table.
But now I added new table in database (created from Management Studio) and added in IdentityDbContext:
public DbSet<City> Cities { get; set; }
But when I run the app now I get error:
The model backing the 'SecurityContext' context has changed since the
database was created. Consider using Code First Migrations to update
the database.
If I delete all tables and run app again City will be created but I wan't to be more flexible.
So what I want to do is that I can create all database tables and to create my POCO classes in project later so I can use EF for data access.
I don't want EF to create classes for me (I feel more secure when connect those things alone).
Also (I know that it is possible but just don't know how) can I prevent asp Identity to create tables alone?
To sum whole question. I want to use EF but I want to create my database myself including Identity tables. How can I do this?
You can turn off the EF initializer and manage the tables and mappings yourself.
Disable the database initializer in the constructor like this...
public SecurityContext()
: base("DefaultConnection")
{
Database.SetInitializer<SecurityContext>(null);
}
Then you can just take the schema that EF has created thus far and manage it yourself (you can remove the migrations history table). I recommend using a SQL Server Database project so that you can source control your schema. It's now up to you to update the DbContext when the schema changes.
You can also disable it through configuration
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="DatabaseInitializerForType YourNameSpace.SecurityContext, YourLibraryName" value="Disabled" />
</appSettings>
</configuration>

Can I change the default schema name in entity framework 4.3 code-first?

Currently I am deploying my application to a shared hosting environment and code-first with migrations has been working great except for one minor hiccup. Everytime I want to push the site I have to use the "Update-Database -script" option because I have to prepend every table name with [dbo] because by default the shared host creates a default schema name that is the same name as the database username.
If I log into my shared host and create a database, I then have to create a user. If I name that user admin, then the tables code-first creates while logged in as admin look something like this "[admin].[BlogPosts]". When the application runs all the tables are created but I get an EF exception because it says "[dbo].[BlogPosts]" is invalid. If I rename the table's schema name to "[dbo]" instead of "[admin]" that fixes it.
To get around this I have to generate a migrations script to be executed manually and add "[dbo]" in front of all the table names because the script only references the tables by their name, not by their schema and their name.
Is there an easy way to get around this? It would be so nice if all I had to do was publish the application and everything just worked. If it wasn't for the schema name discrepancy it would be a one click deploy and everything would be glorious.
For those using Entity Framework 6, just use the HasDefaultSchema method:
public class Contexto : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("MyDefaultDbSchema");
}
}
You could use the ToTable method to specify the schema name. If you do not specify the schema name, EF will by convention use dbo.
public class MyContext
{
private string schemaName = "Foo";
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>().ToTable("MyTable", schemaName);
}
}
In EF Code first, by default, everything is set up based on user access with a managerial access "DBO-Schema" in the SQL Server. But if a specific user is defined to work with a database that is common in shared hosting, then there will no longer be Dbo management access. This time the names of our tables are dbo.tableName, for example, someUser.tableName, and inaccuracy of this point makes it impossible to run the program. To modify and explicitly assign a user connected to a database. If you use metadata, the following method should be used:
[Table("MyTableName", Schema="MySchemaName")]
public class MyClassName
{
//Other Lines...
}
Or (Whether or not Fluent API is customizable as follows:)
modelBuilder.Entity<Blog>().ToTable("MyTableName", schemaName:"MySchemaName");
Notice the following:
a good reference for study:
http://www.c-sharpcorner.com/article/fluent-api-in-code-first-approach/
For database-first implementations, it's easy. Open the edmx file, right click -> Properties and set the default database schema.
For code-first, this article seems most promising: https://web.archive.org/web/20150210181840/http://devproconnections.com/entity-framework/working-schema-names-entity-framework-code-first-design
I would like to add since this is for C#, I have written one below for VB
Public Class ClientDbContext
Inherits DbContext
Public Property Clients As DbSet(Of Client)
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
modelBuilder.HasDefaultSchema("dbo")
End Sub
End Class

Categories

Resources