How to customize the default AspNetUsers data type lengths in ASP.NET Core - entity-framework

I know how to add and edit custom columns to AspNetUsers. I am asking how to change the default ones. I tried using the Fluent API in the DbContext file, but nothing changes. My Visual Studio is - Microsoft Visual Studio Community 2022 (64-bit) - Current
Version 17.3.6, and the project is ASP.NET Core App (MVC) on .NET6
For example, I want to change the length for UserName from nvarchar(256) to nvarchar(50)

For example, I want to change the length for UserName from
nvarchar(256) to nvarchar(50)
You can try below:
Right Click your Database and click New Query, and add below code in it:
ALTER TABLE AspNetUsers ALTER COLUMN UserName VARCHAR (50);
2.Then click Excute.
2.result:
Update
using Entity Framework:
Refer below code(I custom user, you can just use your model) to change your DbContext:
public class AppIdentityDbContext : IdentityDbContext<AppUser>
{
public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder builder)
{
builder
.Entity<AppUser>()
.Property(x => x.UserName)
.HasColumnType("nvarchar(50)");
base.OnModelCreating(builder);
}
}
result:

Related

Map sql view to existing entity in EF 6?

I have a table dbo.Tasks, class for Task, a TaskMap, and add it to the DB context no problem. I also have a database view dbo.vwComplexTaskQuery that returns Tasks. How do I map this view to my task class? I would like to be able to do:
List<Task> Tasks = db.vwComplexTaskQuery.ToList();
Without having to create a vwComplextTaskQuery class that has the same properties and same data annotations.
Simplified Task Class
public class Task
{
public int TaskId { get; set; }
public string Title { get; set; }
}
Simplified Task Map Class
public TaskMap()
{
// Primary Key
this.HasKey(t => t.TaskId);
this.Property(t => t.Title)
.IsRequired()
.HasMaxLength(50);
// Table & Column Mappings
this.ToTable("Tasks");
this.Property(t => t.TaskId).HasColumnName("TaskId");
this.Property(t => t.Title).HasColumnName("Title");
}
Is this possible, if so an example or link to documentation would be great.
I found one solution:
List<Task> tasks = db.Tasks.SqlQuery("Select * from vw_AllTasks").ToList<Task>();
Almost 4 years later... (EF6 has been out that long already? wow...)
EF does not handle VIEWs very well by default: both the EDMX ("Database first") and "Code first" reverse-engineering stuff makes some silly assumptions about views (e.g. that a View can't have the same type as an Entity, a View's Entity doesn't have relationships with other Entities, all of a View's NOT NULL columns must be a composite primary key, etc...
...but if you manually override whatever EF generates such that it thinks a VIEW is a table then it works perfectly correctly (navigation properties, etc). But doing this is kinda difficult and needs to be re-done whenever you update your Model from the database.
Fortunately there's a solution - if you don't mind getting your hands just a bit dirty: There's a third-party, open-source, Entity Framework model generator T4 template (no VS Extensions required: just include 3 files in your project (also available as a NuGet package) called ReversePOCO: https://github.com/sjh37/EntityFramework-Reverse-POCO-Code-First-Generator (disclaimer: I contributed some patches a few months ago specifically to support VIEW handling).
By default, the T4 template in ReversePOCO generates code similar to what EF6's Code First generator creates, but handling VIEWs is straightforward:
In your Database.tt file (where you configure ReversePOCO's Settings object) ensure that Settings.IncludeViews = true.
Look for the Settings.ViewProcessing callback (around like 310 in version 2.37.1).
Uncomment the existing code and modify it to suit your preferences. You will need to list which columns in the view are primary keys.
Look for the Settings.AddForeignKeys callback (around line 326 in version 2.37.1).
Uncomment the existing code and modify it to match the foreign-key relationships you'd like. This will ensure the Navigation properties are created correctly (composite foreign-keys are fully supported).

How can I use Entity Framework to use an existing database, and how can I use migrations to switch between DB versions?

Problem:
You have an existing database that you want to use with EntityFrameworks so that you can make database changes via classes. You also want to be able to use the migration features to switch between versions of the database.
Unfortunately this doesn't work out of the box with an existing database, but you can use the Reverse POCO generator to reverse-engineer your db as if you wrote it from scratch.
Hopefully my step-by-step solution will benefit others, I'm sure I'll be referring to it again in 6 months.
Create new project called MyEF (class library project)
Install the EntityFramework Reverse POCO generator either from here, or within Visual Studio menu Tools|Extensions and Updates menu. select Online|Visual Studio Gallery|Templates|Visual C#|Database, install the EntityFramework Reverse POCO generator.
Using Package Manager console, install EntityFramework by Install-Package EntityFramework
Add a new C# item called MyDB.tt using the template: EntityFramework Rever POCO Code First Generator
Add a connectionStrings section to the app.Config class and point to your database.
e.g.
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=CP8;Initial Catalog=TestDB;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False;" providerName="System.Data.SqlClient" />
</connectionStrings>
In the file MyDB.tt, change "MyDbContext" to "DefaultConnection" or whatever your connection name is. Save the TT file and the Reverse POCO generator will reverse engineer the database and build your code-first classs for you.
If your database has a _MigrationHistory table, delete it!
In the package manager console (PMC) issue the following
Enable-Migrations –EnableAutomaticMigrations -Force
add-migration Initial
Go to your migrations folder and replace the contents of your XXX_Initial.cs class with
namespace MyEf.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class Initial : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
}
From the PMC, issue: update-database
Change your Model by editing the adding a new property in MyDb.cs to the MyTable class:
// MyTable
public class MyTable
{
public int Id { get; set; } // Id (Primary key)
public string Name { get; set; } // Name
public string Sex { get; set; } // Sex
public int? Age { get; set; } // Age
public bool AmIAwesomeOrWhat { get; set; }
}
Rebuild the solution
Issue a command to save your new migration, and update the database
add-migration MyNewProperty
update-database
The following commands will switch to whatever Migration you want.
update-database -targetmigration:Initial
update-database -targetmigration:MyNewProperty

tables are not reflecting on database on vs 2013 by using code first approach of EF 6.1

I have created model classes and using following context in my mvc project on VS2013 and using EF 6.1
public class DataBase : DbContext
{
public class DataBase : DbContext
{
public DataBase()
: base("Db")
{
}
public DbSet<table> table{ get; set; }
}
}
"Db" is my connection string everything ,everything run good but table are not created on my database
Did you try this?
public class DataBase : DbContext
{
public class DataBase : DbContext
{
public DataBase()
: base("Name=Db")
{
}
public DbSet<table> table{ get; set; }
}
}
Set :base() to "Name=Db".
In ef 6 they changed how things work and therefore you need to do some manual steps to be able to generate the database. You have a couple of options I think:
1. Use the packed manager console and run the Update-DataBase command. (You'll have to figure out which flags to use) This might require you to make a blank db with the expected name before running update.
2. Change your database initializer command to:
Database.SetInitializer<UserDbContext>(new MigrateDatabaseToLatestVersion<UserDbContext, Configuration>());
This should make your code always update/create the database. Probably not what you want for production environment though..
3. You create your own initializer, which also has the benefit of seeding data to database on creation. Have a look at http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application <-- towards the end of the article there is an example of such an initializer. The chapter heading is "Set up EF to initialize the database with test data"

Can I get decode an EntityFramework Model from a specified migration?

Apparently IMigrationMetadata.Target encodes the state of the EF model.
Can I use this to reconstruct the model for a particular migration?
Yes, it is possible. I was myself curious what exactly those magic resource strings were storing. By digging into the Entity Framework source (see the DbMigrator.GetLastModel() method), I found out that the IMigrationMetadata.Target just stores a base-64 string containing gzipped XML data. To test this, I created a new console application containing a simple code-first model defined as follows:
public class ContactContext : DbContext
{
public virtual IDbSet<Contact> Contacts { get; set; }
}
public class Contact
{
public int Id {get; set;}
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then I created a migration using the NuGet Package Manager Console:
PM> Enable-Migrations
PM> Add-Migration MyMigration
Next I added the following code to my application's Main() method to decode the value in that string and dump it to the console:
var migration = new MyMigration();
var metadata = (IMigrationMetadata)migration;
var compressedBytes = Convert.FromBase64String(metadata.Target);
var memoryStream = new MemoryStream(compressedBytes);
var gzip = new GZipStream(memoryStream, CompressionMode.Decompress);
var reader = new StreamReader(gzip);
Console.WriteLine(reader.ReadToEnd());
This outputs an EDMX file representing the Entity Data Model associated with my DbContext that created the migration. If I write this output to a file with the .edmx extension, I'm able to open it with Visual Studio and view it in the Entity Designer.
Then if for some reason I wanted to regenerate the DbContext and entity classes that produced the model, I would need only do the following:
Add the .edmx file to a Visual Studio project.
Install the EF 5.x DbContext Generator for C# if I don't already have it.
Add the related T4 templates by selecting Add -> New Item from project node context menu.
Modify the newly added .tt files, replacing $edmxInputFile$ with the name of my .edmx file.
Watch as the two templates magically regenerate my code-first types to their respective .cs files.
Hope that answers your question! :-D
I created a small console app to export EDMX from the Model column of the __MigrationHistory table https://github.com/andreydil/EfMigrationModelDecoder
You can choose specific migration using /migration parameter, i.e:
EfMigrationModelDecoder.Cli.exe "<connectionString here>" /migration:Init
I created a PowerShell script to extract the latest migration from a DB to a edmx-file.
https://gist.github.com/otto-gebb/93d021c8fd300646dba0073a77585a94
You can also use SQL...
SELECT CONVERT(xml, DECOMPRESS(Model)) FROM [dbo].[__MigrationHistory] WHERE MigrationId = 'NameOfMigration'

Unique Constraint with Entity Framework using Code First Migrations

I am doing entity framework (v 5) code first migrations, on an MVC 4 application. I would like to add a unique constraint at the database level.
I know this can be done when creating the table, but I already have a table.
http://msdn.microsoft.com/en-US/data/jj591621
I have tried the following, marked as answer answer: Unique constraint with EFCodeFirst and SqlCe4
My database context differes slightly, I supply the connection name is as follows
public AppDatabaseContext() : base("MyConnectionDBContext")
When I use the Package Management Console to update the database, the overridden seed method is not called:
protected override void Seed(AppDatabaseContext context)
I have also tried the following: http://romiller.com/2010/07/31/ef-ctp4-tips-tricks-running-additional-ddl/
I did not use a nested class, this is because it seemed as if I had to registere the initializer via the app.config. I could not get it working while initializing it in code. The InitializeDatabase is called, but the following condition is never true:
(!context.Database.Exists() || !context.Database.ModelMatchesDatabase())
This is because this happens after the migrations have been run...
I also tried this at one stage: Unique Constraint in Entity Framework Code First, it was the same problem as before, this condition was never returning true.
Ideally, I would like to include some standard SQL in my migration file. Is there a way to do that? If not, where can I see how to achieve this with using code first migrations?
Thanks!
UPDATE:
Is there any reason why I can't use the SQL function?
public override void Up()
{
AddColumn("Posts", "Abstract", c => c.String());
Sql("UPDATE Posts SET Abstract = LEFT(Content, 100) WHERE Abstract IS NULL");
}
Obviously using the correct SQL...
With code first migrations, I've just used this in the Up() method to add a unique index on a single column:
CreateIndex(table: "Organisations",
column: "Name",
unique: true, // unique index
name: "MyIndex");
...and then in the Down() method:
DropIndex(table: "Organisations",
name: "MyIndex");
Is that what you're after?
Since EF 6.1 you can now do this in your model with either
an attribute
[Index("IX_UniqueName", IsUnique = true)]
public string Name {get;set;}
or fluent
Property(s => s.Name).HasColumnAnnotation(IndexAnnotation.AnnotationName,
new IndexAnnotation(
new IndexAttribute("IX_UniqueName") { IsUnique = true }));
The fluent method isn't perfect as its crazy verbose IMO but at least its possible now.
More deets on Arthur Vickers blog http://blog.oneunicorn.com/2014/02/15/ef-6-1-creating-indexes-with-indexattribute/
You can just scaffold a new migration using the Add-Migration command from your package manager console. Once the empty migration is created, in the Up method, you can use the CreateIndex method of the DbMigration class to create your new index. It would look like something like this: CreateIndex("dbo.Accounts", "AccessKey", unique: true);