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>
{
}
Related
Hi I am trying to build angular 2 web application using WebAPI, Entityframework that is loosely coupled using dependency injection. I am using unity for dependency injection. I have created multiple projects in one solution to address the separation concerns.
I have configured the dependency in unity.config however when i execute the webapi application and type the following url http://localhost:8702/api/allcustomers , I get message saying the customer controller doesn't have parameter-less constructor. I have set my break points in unity.config which never get hit
I would like to to understand if my implementation is correct as well
Below is the structure of my solution
CustomerOrder.Business.Objects
CustomerOrder.Data.Objects (references the business object)
CustomerOrder.Service.Api (references business object and service implementation)
CustomerOrder.Service.Implementation (references business objects and data objects)
CustomerOrder.Web (Yet to implement)
Below is the code
CustomerOrder.Business.Objects
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public int? Zip { get; set; }
}
CustomerOrder.Data.Objects
public class CustomerDao : ICustomerDao
{
IEnumerable<CustomerOrder.BusinessObjects.Customer> ICustomerDao.GetAllCustomers()
{
using (var customerOrderContext = new Entities())
{
return (from customer in customerOrderContext.Customers
select new CustomerOrder.BusinessObjects.Customer
{
Id = customer.Id,
FirstName = customer.FirstName,
LastName = customer.LastName,
Address = customer.Address,
City = customer.City,
Email = customer.Email,
Gender = customer.Gender,
State = customer.State,
Zip = customer.Zip
}).ToList();
}
}
}
public interface ICustomerDao
{
/// <summary>
/// Get All Customers
/// </summary>
/// <returns></returns>
IEnumerable<Customer> GetAllCustomers();
}
public interface IDaoFactory
{
ICustomerDao CustomerDao { get; }
}
}
public class DaoFactory : IDaoFactory
{
public DaoFactory(ICustomerDao CustomerDao, IProductDao ProductDao, IOrderDao OrderDao)
{
this.CustomerDao = CustomerDao;
}
public ICustomerDao CustomerDao { set; get; }
}
CustomerOrder.Service.Api
Unity.Config
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<ICustomerProvider, CustomerProvider>();
container.RegisterType<IOrderProvider, OrderProvider>();
container.RegisterType<IProductProvider, ProductProvider>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
CustomerController.cs
public class CustomerController : ApiController
{
private ICustomerProvider customerProvider;
public CustomerController(ICustomerProvider customerProvider)
{
this.customerProvider = customerProvider;
}
[Route("api/allcustomers")]
public IEnumerable<Customer> GetAllCustomers()
{
return customerProvider.GetAllCustomers();
}
CustomerOrder.Service.Implementation
public interface ICustomerProvider
{
IEnumerable<BusinessObjects.Customer> GetAllCustomers();
}
public class CustomerProvider : ICustomerProvider
{
private readonly IDaoFactory dataAccess;
public CustomerProvider(IDaoFactory dalFactory)
{
this.dataAccess = dalFactory;
}
public IEnumerable<BusinessObjects.Customer> GetAllCustomers()
{
IList<BusinessObjects.Customer> customerCollection = new List<BusinessObjects.Customer>();
dataAccess.CustomerDao.GetAllCustomers();
return customerCollection;
}
}
Context Class
namespace CustomerOrderData.EF
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class Entities : DbContext
{
public Entities()
: base("name=Entities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<OrderDetail> OrderDetails { get; set; }
public virtual DbSet<Order> Orders { get; set; }
public virtual DbSet<Product> Products { get; set; }
}
}
In CustomerProvider, the IDaoFactory is probably not getting resolved because it's not registered. Add this to the Unity.Config:
container.RegisterType<IDaoFactory , DaoFactory >();
Please try including a parameterless constructor into the customer controller.
public CustomerController() {}
You should register not only IDaoFactory and his constructor dependencies
container.RegisterType<IDaoFactory, DaoFactory>();
container.RegisterType<ICustomerDao, CustomerDao>();
container.RegisterType<IOrderDao, OrderDao>();
container.RegisterType<IProductDao, ProductDao>();
I want to remove a row in database and insert it again with the same Id, It sounds ridiculous, but here is the scenario:
The domain classes are as follows:
public class SomeClass
{
public int SomeClassId { get; set; }
public string Name { get; set; }
public virtual Behavior Behavior { get; set; }
}
public abstract class Behavior
{
public int BehaviorId { get; set; }
}
public class BehaviorA : Behavior
{
public string BehaviorASpecific { get; set; }
}
public class BehaviorB : Behavior
{
public string BehaviorBSpecific { get; set; }
}
The entity context is
public class TestContext : DbContext
{
public DbSet<SomeClass> SomeClasses { get; set; }
public DbSet<Behavior> Behaviors { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Entity<SomeClass>()
.HasOptional(s => s.Behavior)
.WithRequired()
.WillCascadeOnDelete(true);
}
}
Now this code can be executed to demonstrate the point
(described with comments in the code below)
using(TestContext db = new TestContext())
{
var someClass = new SomeClass() { Name = "A" };
someClass.Behavior = new BehaviorA() { BehaviorASpecific = "Behavior A" };
db.SomeClasses.Add(someClass);
// Here I have two classes with the state of added which make sense
var modifiedEntities = db.ChangeTracker.Entries()
.Where(entity => entity.State != System.Data.Entity.EntityState.Unchanged).ToList();
// They save with no problem
db.SaveChanges();
// Now I want to change the behavior and it causes entity to try to remove the behavior and add it again
someClass.Behavior = new BehaviorB() { BehaviorBSpecific = "Behavior B" };
// Here it can be seen that we have a behavior A with the state of deleted and
// behavior B with the state of added
modifiedEntities = db.ChangeTracker.Entries()
.Where(entity => entity.State != System.Data.Entity.EntityState.Unchanged).ToList();
// But in reality when entity sends the query to the database it replaces the
// remove and insert with an update query (this can be seen in the SQL Profiler)
// which causes the discrimenator to remain the same where it should change.
db.SaveChanges();
}
How to change this entity behavior so that delete and insert happens instead of the update?
A possible solution is to make the changes in 2 different steps: before someClass.Behavior = new BehaviorB() { BehaviorBSpecific = "Behavior B" }; insert
someClass.Behaviour = null;
db.SaveChanges();
The behaviour is related to the database model. BehaviourA and B in EF are related to the same EntityRecordInfo and has the same EntitySet (Behaviors).
You have the same behaviour also if you create 2 different DbSets on the context because the DB model remains the same.
EDIT
Another way to achieve a similar result of 1-1 relationship is using ComplexType. They works also with inheritance.
Here an example
public class TestContext : DbContext
{
public TestContext(DbConnection connection) : base(connection, true) { }
public DbSet<Friend> Friends { get; set; }
public DbSet<LessThanFriend> LessThanFriends { get; set; }
}
public class Friend
{
public Friend()
{Address = new FullAddress();}
public int Id { get; set; }
public string Name { get; set; }
public FullAddress Address { get; set; }
}
public class LessThanFriend
{
public LessThanFriend()
{Address = new CityAddress();}
public int Id { get; set; }
public string Name { get; set; }
public CityAddress Address { get; set; }
}
[ComplexType]
public class CityAddress
{
public string Cap { get; set; }
public string City { get; set; }
}
[ComplexType]
public class FullAddress : CityAddress
{
public string Street { get; set; }
}
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; }
}
Assume that I have the following little console application which uses Entity Framework 5:
class Program {
static void Main(string[] args) {
using (var ctx = new ConfContext()) {
var personBefore = ctx.People.First();
Console.WriteLine(personBefore.Name);
personBefore.Name = "Foo2";
ctx.SaveChanges();
var personAfter = ctx.People.First();
Console.WriteLine(personAfter.Name);
}
Console.ReadLine();
}
}
public class ConfContext : DbContext {
public IDbSet<Person> People { get; set; }
public IDbSet<Session> Sessions { get; set; }
}
public class Person {
[Key]
public int Key { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public DateTime? BirthDate { get; set; }
public ICollection<Session> Sessions { get; set; }
}
public class Session {
[Key]
public int Key { get; set; }
public int PersonKey { get; set; }
public string RoomName { get; set; }
public string SessionName { get; set; }
public Person Person { get; set; }
}
As you can see, I am changing the name of the record and saving it. It works but it feels like magic to me. What I am doing in all of my applications is the following one (to be more accurate, inside the Edit method of my generic repository):
static void Main(string[] args) {
using (var ctx = new ConfContext()) {
var personBefore = ctx.People.First();
Console.WriteLine(personBefore.Name);
personBefore.Name = "Foo2";
var entity = ctx.Entry<Person>(personBefore);
entity.State = EntityState.Modified;
ctx.SaveChanges();
var personAfter = ctx.People.First();
Console.WriteLine(personAfter.Name);
}
Console.ReadLine();
}
There is no doubt that the second one is more semantic but is there any other obvious differences?
Well the second code block where you explicitly set the entity state is redundant, as the change tracker already knows that the entity is modified because the context knows about the entity (as you query the context to retrieve the entity).
Setting (or painting) the state of the entity would be more useful when working with disconnected entities, for example in an n-tier environment where the entity was retrieved in a different context and sent to a client for modification, and you wish to mark those changes back on the server using a different context.
Otherwise, the first code block is cleaner in my opinion.
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.