Why is EF code first throwing model backing context exception? Using 4.0.3 - entity-framework

Heres the exception:
The model backing the 'ScannerContext' context has changed since the
database was created. Consider using Code First Migrations to update
the database (http://go.microsoft.com/fwlink/?LinkId=238269).
I get this everytime I run my application. I cant figure out what it means. I think it means something isn't mapped correctly, but I cant figure out what. I am using the code first model, and I have an existing database that I want totally custom mappings for. Right now, I have everything in my classes named the same as my database to eliminate possible cuases.
The Exception is thrown when I try to .Add() the entity to the context.
The Entity as it is in the Database
The Entity in my DataLayer
public class EAsset
{
public int i_GID { get; set; }
public EAssetType Type { get; set; }
public EOrgEnvironment Environment { get; set; }
public EUser Contact { get; set; }
public string s_Name { get; set; }
public string s_Role { get; set; }
public DateTime d_Added { get; set; }
public DateTime d_LastUpdated { get; set; }
public bool b_Retired { get; set; }
public EAsset()
{
Type = new EAssetType();
Environment = new EOrgEnvironment();
Contact = new EUser();
d_Added = DateTime.Now;
d_LastUpdated = DateTime.Now;
}
}
The Context Object (with attempted table mapping and key assignment)
public class ScannerContext : DbContext
{
public ScannerContext()
: base("LabDatabase") { }
public DbSet<EAsset> EAssets { get; set; }
public DbSet<EAssetType> EAssetTypes { get; set; }
public DbSet<EOrgEnvironment> EOrgEnvironments { get; set; }
public DbSet<EUser> EUsers { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EAsset>().HasKey(k=>k.i_GID).ToTable("t_Assets");
modelBuilder.Entity<EAssetType>().HasKey(k => k.i_ID).ToTable("t_Asset_Types");
modelBuilder.Entity<EOrgEnvironment>().HasKey(k => k.i_ID).ToTable("t_Org_Environments");
modelBuilder.Entity<EUser>().HasKey(k => k.i_ID).ToTable("t_Users");
base.OnModelCreating(modelBuilder);
}
}
The Program
class Program
{
static void Main(string[] args)
{
EAsset Entity = new EAsset { s_Name = "jewri-pc" };
var sContext = new ScannerContext();
sContext.EAssets.Add(Entity);
sContext.SaveChanges();
}
}

For EF runtime version 4.0.3 / version 4.0
public class ScannerContext : DbContext
{
public ScannerContext()
: base("LabDatabase") { }
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<ScannerContext>(null); // <--- This is what i needed
...
base.OnModelCreating(modelBuilder);
}
}
With that code installed I am now chasing errors related to having all my relationships accounted for in the model. The FK Constraints are forcing me to add the missing relational items.
Found info here. They explain the importance a bit.
The model backing the <Database> context has changed since the database was created

Enable-Migrations -ContextTypeName EmployeeProject.Models.DepartmentContext
Means you have to write your project name.Models.Context name
It will work.

Related

EF 6 - How to get DbSet by table name

I have a DbContext that looks like this:
public partial class MyDbConnectionConnection : DbContext
{
public MyDbConnectionConnection()
: base("name=MyDbConnectionConnection ")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<Name> tbName{ get; set; }
public DbSet<Surname> tbSurname{ get; set; }
public DbSet<Address> tbAddress{ get; set; }
public DbSet<Currency> tbCurrency { get; set; }
}
}
and I need to search through this Context and find data set that matches the table name for example:
public dynamic getCorrectEntity()
{
MyDbConnectionConnection Context = new MyDbConnectionConnection();
var dbset = Context.Set(Type.GetType("tbName"));
return dbset;
}
where "tbName" is name of DbSet.
I cannot get anything!
In this line of code Type.GetType("tbName") it returns value null.
I just need to mentioned that I googled, try all examples I found here in the last couple of hours but nothing helps :(
Does anyone know how to get entity on this way?
P.S. I also try all this using Assembly.GetType(name). It didn't help...

ef core 1.1 Autogenerated column using ValueGeneratedOnAdd

Using EfCore 1.1, I am trying to have a autogenerated column using ValueGeneratedOnAdd. The problem is i am always getting value as "0". Do i have to manually do anything with the database table ?
Here is my model
public class Contact
{
public int Id { get; set; }
// This needs to be auto generated
public Int32 ContactIndex { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public DateTime LastAccessed { get; set; }
}
This is how my OnModelCreating looks like
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Contact>()
.Property(c => c.ContactIndex)
.ValueGeneratedOnAdd();
// I tried following as well but it did't work
// .HasDefaultValueSql("IDENTITY(int, 1,1)");
;
}
ok I figured how to do it, but i really wanted to do that without using any annotations, and i still cannot figure out how to do it without annotations on model. So here is my solution.
You need to annotate your filed in the model like following
public class Contact
{
public int Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Int32 ContactIndex { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public DateTime LastAccessed { get; set; }
}
and add OnModelCreating in your context class. This will tell entity framework to ignore the column while adding or updating records. Make sure you calling method .ValueGeneratedAddOrUpdate( ). If you use only .ValueGeneratedAdd( ) you will get errors while making updates.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Contact>()
.Property(c => c.ContactIndex)
.ValueGeneratedOnAddOrUpdate();
;
}
Generate and run your migrations and your migrations should include "SqlServerValueGenerationStrategy.IdentityColumn"
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "ContactIndex",
table: "Contact",
nullable: false,
defaultValue: 0)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
}

EF code first telling me to do the migration for db object which is already is in db

i am working with EF code first. so initially i have no tables in database. so i wrote some class and when query those class then i saw EF code first create those tables in db but when i create sql server view in db and later map that view with my code in c# & EF project and when i try to query that view then i was getting error message as follows.
Additional information: The model backing the 'TestDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database
i understand that EF is telling me to do the migration but if i migrate then EF will create that view in db again when the view is in db already exist.
so tell me how could i inform EF that my view is already is in db so migration is not required.
please guide me. thanks
EDIT 1
first time my database has no table. so i wrote some classes like below one.
public class CustomerBase
{
public int CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
}
public class Customer : CustomerBase
{
public virtual List<Addresses> Addresses { get; set; }
}
public class Addresses
{
[Key]
public int AddressID { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public bool IsDefault { get; set; }
public virtual List<Contacts> Contacts { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; }
}
public class Contacts
{
[Key]
public int ContactID { get; set; }
public string Phone { get; set; }
public string Fax { get; set; }
public bool IsDefault { get; set; }
public int AddressID { get; set; }
public virtual Addresses Customer { get; set; }
}
public class TestDBContext : DbContext
{
public TestDBContext()
: base("name=TestDBContext")
{
}
public DbSet<Customer> Customer { get; set; }
public DbSet<Addresses> Addresses { get; set; }
public DbSet<Contacts> Contacts { get; set; }
}
when i query the customer like below query then EF create all required tables in db behind the curtains.
var bsCustomer = (from cu in db.Customer
where (cu.CustomerID == 2)
select new
{
cu,
Addresses = from ad in cu.Addresses
where (ad.IsDefault == true)
from ct in ad.Contacts
select ad,
}).ToList();
later i create a view in db and refer that view in code like below one.
public partial class vwCustomer
{
[Key]
public int CustomerID { get; set; }
public string FirstName { get; set; }
}
public class vwCustomerConfiguration : EntityTypeConfiguration<vwCustomer>
{
public vwCustomerConfiguration()
{
this.HasKey(t => t.CustomerID);
this.ToTable("vwCustomers");
}
}
so now my DbContext look like below one with view class reference
public class TestDBContext : DbContext
{
public TestDBContext()
: base("name=TestDBContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new vwCustomerConfiguration());
}
public DbSet<Customer> Customer { get; set; }
public DbSet<Addresses> Addresses { get; set; }
public DbSet<Contacts> Contacts { get; set; }
public virtual DbSet<vwCustomer> vwCustomers { get; set; }
}
Error occur the moment i try to query the view
using (var db = new TestDBContext())
{
var listMyViews = db.vwCustomers.ToList();
}
the error was Additional information: The model backing the 'TestDBContext' context has changed since the database was created. Consider using Code First Migrations to update the database
thanks
Another way we can do it and it solve my problem. see the code.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<YourDbContext>(null);
base.OnModelCreating(modelBuilder);
}
code taken from here https://stackoverflow.com/a/6143116/6188148
we can follow this approach too.
public partial class AddingvwCustomer : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
i guess this will works too but not tested myself.
we can use the Fluent API to configure it using the Ignore method:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Ignore<MyClass>();
}
Add new migration as normally and from the migration code in Up (and Down) method remove code that tries to create new table manually (call to CreateTable method in Up and DropTable in Down). Then apply migration to your db and everything works perfectly.
Unfortunately automatic migration generation is not very intelligent tool and very often one need to manually specify how the database should be altered. In the documentation for EF migrations it is stated that it is perfectly fine to edit manually migrations code.

C# entity framework MVC second run error

I am creating db and initializing data with code below, if DB doesnt exist, it creates db and populate it, when I run application second time I get error
Cannot drop database "aspnet-app" because it is currently in use.
Application_start, with initializations
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
Database.SetInitializer(new ComponentDbInitialize());
ComputerContext context = new ComputerContext();
context.Database.Initialize(true); //here it fails on second run
context.SaveChanges();
}
ComputerContext
public ComputerContext():base("name=Default")
{
}
public DbSet<Computer> Computers { get; set; }
public DbSet<Motherboard> Motherboards { get; set; }
public DbSet<CPU> CPUs { get; set; }
public DbSet<Case> Cases { get; set; }
public DbSet<HDD> HDDs { get; set; }
public DbSet<RAM> RAMs { get; set; }
public DbSet<GPU> GPUs { get; set; }
public DbSet<PSU> PSUs { get; set; }
}
Initialize class
public class ComponentDbInitialize : DropCreateDatabaseAlways<ComputerContext>
{
protected override void Seed(ComputerContext context)
{
GetCpu().ForEach(p => context.CPUs.Add(p));
GetGpu().ForEach(p => context.GPUs.Add(p));
GetCase().ForEach(p => context.Cases.Add(p));
GetHdd().ForEach(p => context.HDDs.Add(p));
GetMb().ForEach(p => context.Motherboards.Add(p));
GetPsu().ForEach(p => context.PSUs.Add(p));
GetRam().ForEach(p => context.RAMs.Add(p));
context.SaveChanges();
}
private static List<CPU> GetCpu() .....
private static List<GPU> GetGpu().....
private static List<HDD> GetHdd()....
private static List<Case> GetCase()....
private static List<Motherboard> GetMb()....
private static List<PSU> GetPsu()....
private static List<RAM> GetRam()....
I get same error even with
context.Database.Initialize(false);
Thank you for any help/advice
Your initialiser is using the DropCreateDatabaseAlways class which, as it suggests, drops that database every time the application is initialised.
Instead perhaps you could use CreateDatabaseIfNotExists or DropCreateDatabaseIfModelChanges:
public class ComponentDbInitialize : CreateDatabaseIfNotExists<ComputerContext>
{
}

check if a property is ignored by EntityFramework

Using EntityFramework 4.3 w/POCOs.
how can I check if a property on a model is ignored or not.
In my DBContext Class Hierarchy I am ignoring a property by
modelBuilder.Entity<EClass>().Ignore (f => f.IgnoredProperty());
In my BaseContext class, I need to check if that property is ignored or not.
private void ProcessGlobalConvention(DbModelBuilder modelBuilder, IGlobalConvention convention)
{
modelBuilder.Entity<typeof(this.GetType())>("Ignored Property");
}
How can I do that?
Thanks
Use the EF power tools http://www.infoq.com/news/2013/10/ef-power-tools-beta4 to view your model. Is the property there?
Create a database. Is the column there?
Look at the Database.LogSqlEvents http://blog.oneunicorn.com/2013/05/08/ef6-sql-logging-part-1-simple-logging/ and parse the sql to see if the field name appears...
....unless you really want a code solution...?
IN WHICH CASE
New up your DbContext
Create one record and add it to the relevant DbSet
Get the DbEntityEntry
Look in CurrentValues.PropertyNames. Is your property there?
[TestMethod]
public void CreateDatabase()
{
Database.SetInitializer(new DropCreateDatabaseAlways<HomesContext>());
var db = new HomesContext();
Assert.IsFalse(db.Homes.Any());
var home = db.Homes.Create();
db.Homes.Add(home);
var entry = db.Entry(home);
Assert.IsTrue(entry.CurrentValues.PropertyNames.Contains("MaxResidents"));
Assert.IsTrue(entry.CurrentValues.PropertyNames.Contains("MaxStaff"));
Assert.IsFalse(entry.CurrentValues.PropertyNames.Contains("CurrentResidents"));
Assert.IsFalse(entry.CurrentValues.PropertyNames.Contains("CurrentStaff"));
}
public class HomesContext:DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Home>().Ignore(x => x.CurrentResidents);
base.OnModelCreating(modelBuilder);
}
public DbSet<Home> Homes { get; set; }
}
public class Home
{
public int HomeId { get; set; }
public string HomeName { get; set; }
public int MaxResidents { get; set; }
public int MaxStaff { get; set; }
public int CurrentResidents { get; set; }
[NotMapped]
public int CurrentStaff { get; set; }
}