I am trying to update my database by using automatic migrations. I have recently added some properties to the Identity Model:
namespace CISC_Website.Models
{
public class ApplicationUser : IdentityUser
{
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool ConfirmedEmail { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("CISCDb")
{
}
}
}
However whenever I run the update-database command these changes are not pushed as my user tables are still the same as when they were first created.
Here is the contents of my migrations folder:
namespace CISC_Website.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Collections.Generic;
internal sealed class Configuration : DbMigrationsConfiguration<CISC_Website.Models.CISCDb>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(CISC_Website.Models.CISCDb context)
{
//seed data...
}
}
}
I know originally when the enable migrations command was run, the identity model was represented as such:
namespace CISC_Website.Models
{
public class ApplicationUser : IdentityUser
{
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
}
}
Any idea how i can get these tables recognized??
Your application has two DbContexts: CISCDb and IdentityDbContext and you have configured migrations only for your CISCDb context. Therefore changes in the Identity context are not included in the CISCDb migrations.
You should be able to configure the migrations for the IdentityContext the same way you did for the other context to get it working.
Related
I am working with a database where I have more than 75 tables and I am using the repository and unit of work patterns with Entity Framework in an ASP.NET MVC project. I am little bit confused and some query in my mind about object creation. When UnitOfWork initializes, it creates object for all table's entity which is present in UnitOfWork. So it can be heavy for application load.
Here is the interface of unit of work:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Application.Repository;
using Application.Repository.General;
namespace Application.UnitOfWorks
{
public interface IUnitOfWork : IDisposable
{
IGeneralRegionMasterRepository GeneralRegionMasters { get; }
IGeneralSubRegionMasterRepository GeneralSubRegionMasters { get; }
IGeneralCountryMasterRepository GeneralCountryMasters { get; }
IGeneralStateMasterRepository GeneralStateMasters { get; }
IGeneralCityMasterRepository GeneralCityMasters { get; }
int Complete();
}
}
Implementation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Application.EntityFramework;
using Application.Repository;
using Application.Repository.General;
namespace Application.UnitOfWorks
{
public class UnitOfWork : IUnitOfWork
{
public readonly InventoryDbContext _context;
public UnitOfWork(InventoryDbContext context)
{
_context = context;
GeneralRegionMasters = new GeneralRegionMasterRepository(_context);
GeneralSubRegionMasters = new GeneralSubRegionMasterRepository(_context);
GeneralCountryMasters = new GeneralCountryMasterRepository(_context);
GeneralStateMasters = new GeneralStateMasterRepository(_context);
GeneralCityMasters = new GeneralCityMasterRepository(_context);
}
public IGeneralRegionMasterRepository GeneralRegionMasters { get; private set; }
public IGeneralSubRegionMasterRepository GeneralSubRegionMasters { get; private set; }
public IGeneralCountryMasterRepository GeneralCountryMasters { get; private set; }
public IGeneralStateMasterRepository GeneralStateMasters { get; private set; }
public IGeneralCityMasterRepository GeneralCityMasters { get; private set; }
public int Complete()
{
return _context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
}
I want to know about performance effect of it on application. Thank you in advance for help.
I've run into the same problem that you are describing in the past. The structure of the code just feels really heavy since you are creating new instances of 70 repositories even though you may only need one of them. This is why I've just started to avoid adding my own UoW and Repositories when using EF directly because EF already has Repositories and UoW built in (DbSets = Repos, Save Changes does UoW save at the end of all DbSet changes). If you don't want to code directly against a DbContext, just have your DbContext implement the IUnitOfWork interface directly and go off of that. Also have all your DbSets exposed on that UnitOfWork. Then you could have it also implement IMyDbContext and have that expose the DbSets and have this interface also implement IUnitOfWork (or have DbContext -> IMyDbContext -> IUnitOfWork) or break them up if you don't want repo code having access to Save at the bottom. This just ends up making it easier in the long run. No weird code to maintain, no classes to create. If you switch to not use EF, you can still use those same interfaces behind the scenes and the only thing that would have to change would be the DbSet implementation (maybe you can even get that to be generic - create your on DbSets that implement another interface, too). Personally, I'm going down the CQS path so I don't have to worry about repos or UoW anymore. :)
Edit
Example the best I can here! :)
public interface IUnitOfWork
{
int Complete();
Task<int> CompleteAsync();
}
public interface IInventoryDbContext : IUnitOfWork
{
DbSet<GeneralRegionMaster> GeneralRegionMasters { get; }
DbSet<GeneralSubRegionMaster> GeneralSubRegionMasters { get; }
... etc
}
public class MyDbContext : DbContext, IInventoryDbContext
{
public DbSet<GeneralRegionMaster> GeneralRegionMasters { get; set; }
public DbSet<GeneralSubRegionMaster> GeneralSubRegionMasters { get; set;
}
public int Complete() => this.SaveChanges();
public Task<int> CompleteAsync() => this.SaveChangesAsync();
}
If you did a controller level only:
public class MyController : Controller
{
private readonly IInventoryDbContext _context;
public MyController(IInventoryDbContext context)
{
_context = context;
}
public JsonResult CreateGeneralRegionMaster(GeneralRegionMaster entity)
{
_context.GeneralRegionMaster.Add(entity);
var result = _context.Complete();
return Json(result == 1);
}
}
Again, you could do something different for the DbSets and do this instead:
public interface IRepo<T> where T: class
{
// Expose whatever methods you want here
}
public class MyDbSet<T> : DbSet<T>, IRepo<T> where T: class
{
}
Then this changes:
public interface IInventoryDbContext : IUnitOfWork
{
IRepo<GeneralRegionMaster> GeneralRegionMasters { get; }
IRepo<GeneralSubRegionMaster> GeneralSubRegionMasters { get; }
... etc
}
public class MyDbContext : DbContext, IInventoryDbContext
{
public MyDbSet<GeneralRegionMaster> GeneralRegionMasters { get; set; }
public MyDbSet<GeneralSubRegionMaster> GeneralSubRegionMasters { get; set; }
public IRepo<GeneralRegionMaster> GeneralRegionMastersRepo => GeneralRegionMasters;
public IRepo<GeneralSubRegionMaster> GeneralSubRegionMastersRepo => GeneralSubRegionMasters;
public int Complete() => this.SaveChanges();
public Task<int> CompleteAsync() => this.SaveChangesAsync();
}
Re:
When UnitOfWork initializes, it creates object for all table's entity which is present in UnitOfWork. So it can be heavy for application load.
You don't need to initialize all the repo instances in the UoW constructor.
You can create them when they are required in the corresponding getters (lazy initialization):
private IGeneralRegionMasterRepository _generalRegionMasters;
public IGeneralRegionMasterRepository GeneralRegionMasters {
get {
if (_generalRegionMasters == null) {
_generalRegionMasters = new GeneralRegionMasterRepository(_context);
}
return _generalRegionMasters;
}
}
I m working on an existing MVC project.When my context class inherited from DBContext everythink is fine but when i changed it to IdentityDbContext i get that error.The error occured in that line :
var makaleler = context.Makale.ToList();
my controller:
using mvcblogdeneme.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace mvcblogdeneme.Controllers
{
public class HomeController : Controller
{
// GET: Home
BlogDatabaseContext context = new BlogDatabaseContext();
public ActionResult Index()
{
return View();
}
public ActionResult CategoryWidgetGetir()
{
var kat = context.Kategori.ToList();
return View(kat);
}
public ActionResult TumMakalelerGetir()
{
var makaleler = context.Makale.ToList();
return View("MakaleListele", makaleler);//makalelistele bi partial view
}
}
}
this is my model:
namespace mvcblogdeneme.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("Makale")]
public partial class Makale
{
public int Id { get; set; }
[Required]
[StringLength(150)]
public string Baslik { get; set; }
[Required]
public string Icerik { get; set; }
public DateTime YayimTarihi { get; set; }
public int KategoriID { get; set; }
public virtual Kategori Kategori { get; set; }
}
}
If the exception message shows like this and DbContext is being used:
EntityType '[[table name]]' has no key defined. Define the key for
this EntityType.
EntityType: EntitySet '[[entity name]]' is based on type '[[table name]]'
that has no keys defined.
Then definitely you need to use KeyAttribute on Id property to mark it as primary key field inside table model class and problem will solved:
[Table("Makale")]
public partial class Makale
{
// if the ID also set as auto-increment, uncomment DatabaseGenerated attribute given below
// [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int Id { get; set; }
[Required]
[StringLength(150)]
public string Baslik { get; set; }
[Required]
public string Icerik { get; set; }
public DateTime YayimTarihi { get; set; }
public int KategoriID { get; set; }
public virtual Kategori Kategori { get; set; }
}
However, if the cause is found out coming from IdentityDbContext and EF Code First being used, you need to do these steps (credits to DotNetHaggis):
Create configuration class for IdentityUserLogin & IdentityUserRole:
// taken from /a/20912641
public class IdentityUserLoginConfiguration : EntityTypeConfiguration<IdentityUserLogin>
{
public IdentityUserLoginConfiguration()
{
HasKey(iul => iul.UserId);
}
}
public class IdentityUserRoleConfiguration : EntityTypeConfiguration<IdentityUserRole>
{
public IdentityUserRoleConfiguration()
{
HasKey(iur => iur.RoleId);
}
}
Add those two configurations above inside OnModelCreating method:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new IdentityUserLoginConfiguration());
modelBuilder.Configurations.Add(new IdentityUserRoleConfiguration());
}
At this point, the error should get resolved due to primary key for every identity tables has been set.
Similar issues:
An exception of type 'System.Data.Entity.ModelConfiguration.ModelValidationException' occurred in EntityFramework.dll
Merge MyDbContext with IdentityDbContext
I'm creating initial migration using
Add-Migration InitialCreate
But then when I'm updating my database tables from IdentityDbContext are not created so I get exceptions.
So how do I create migration for AspNetUser tables from IdentityDbContext?
Regards teamol
You can add custom fields to your AspNetUser table in your IdentityModels.cs file.
First add your custom values ito ApplicationUser class in IdentityModels:
namespace YourProjectName.Models
{
public class ApplicationUser : IdentityUser
{
public string Email { get; set; }
public string NameSurname { get; set; }
public string ProfilePhotoRoute { get; set; }
public string Title { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
}
After that, enter "Add-Migration NewMigration" command in package manager console.
Finally, enter "Update-Database" command in package manager console.
If your connection string -which is stated in web.config- is true, you can update succesfully your database with this way.
I have a very simple context
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
namespace WindowsFormsApplication1
{
[Table("MyParts2")]
public class MyPart2
{
[Browsable(false)]
[Key]
public int Id { get; set; }
}
public class EFProjectDbContext : DbContext
{
public EFProjectDbContext() // used for migrations
: base("name=ApplicationDatabase")
{
Database.SetInitializer(new CreateDatabaseIfNotExists<EFProjectDbContext>());
}
public EFProjectDbContext(string connectionString)
: base(connectionString)
{
if (Database.Exists())
{
// error here is benign uncheck break
var isCompatible = Database.CompatibleWithModel(false); //error occurs here
if (!isCompatible)
{
// uncheck break when this exception type is shown
// note if you are in debug you need to run exe to kick off upgrade
throw new Exception(
"The database is not compatible with the entity model. Drop the database or run migrations");
}
}
else
{
Database.SetInitializer(new CreateDatabaseIfNotExists<EFProjectDbContext>());
}
}
public EFProjectDbContext(DbConnection connection)
: base(connection, false)
{
}
public DbSet<MyPart2> MyParts2 { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
}
}
And i have migrations enabled
If I rename the class name and table attribute and create a migration the up method creates as
public override void Up()
{
RenameTable(name: "dbo.MyParts2", newName: "MyParts3");
}
How does it the create migration realise that the table is a rename and not a drop and re-create ?
Hi I am learning to develop project using code first approach. I am facing a small problem that when i run the command Add-Migration its not identifying the changes even i have enables the AutomaticMigrationsEnabled in config file
here is my code
----------------------------- DbContext file
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EntityCodeFirstSample.DataBaseFiles
{
class EntityCodeFirstSampleContext : DbContext
{
public EntityCodeFirstSampleContext()
: base("name=DbConnectionString")
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<EntityCodeFirstSampleContext, EntityCodeFirstSample.Migrations.Configuration>("DbConnectionString"));
}
public DbSet<Publisher> Publishers { get; set; }
public DbSet<Book> Books { get; set; }
public DbSet<Sample> Samples { get; set; }
public DbSet<Venkat> Venkats { get; set; }
}
}
----------------- Configurations file ---------------------------------
namespace EntityCodeFirstSample.Migrations
{
internal sealed class Configuration : DbMigrationsConfiguration<EntityCodeFirstSample.DataBaseFiles.EntityCodeFirstSampleContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(EntityCodeFirstSample.DataBaseFiles.EntityCodeFirstSampleContext context)
{
}
}
}
------------------------------------------- Model File ---------------------
namespace EntityCodeFirstSample.DataBaseFiles
{
[Table("Venkat")]
public class Venkat
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public int NotaryCode { get; set; }
}
}
After running the command Add-Migration VenkatClass it is generating the migration file as below
namespace EntityCodeFirstSample.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class VenkatClass : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
}
when AutomaticMigrationsEnabled = true then you don't have to add Migration because when you will execute your program the EF will look after for any change on the fly and update your database. If you want to control then set the AutomaticMigrationsEnabled = false. Then you should be able to see the difference when Add-Migration is being called.
Please read: https://msdn.microsoft.com/en-us/data/jj554735.aspx
and then read this: https://msdn.microsoft.com/en-us/data/jj591621.aspx
Run:
update-database
Make sure that the project is set default where the connection string is stored.
If it does not return any error then it is all good to go. You should able to see that the update has already occured and your new changes must have reflect already.