Why doesn't DropCreateDatabaseAlways drop the database when the model changes? - c#

I have a model with one entity:
namespace TestMigration
{
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public int FollowersCount { get; set; }
//public int BloggerAge { get; set; }
}
}
The Initializer class:
public class DataInitializer : DropCreateDatabaseAlways<BlogContext>
{
protected override void Seed(BlogContext context)
{
var blogs = new List<Blog>
{
new Blog {FollowersCount=456, Name="ABC", Url="abc.com" },
new Blog {FollowersCount=789, Name="DEF", Url="def.com" },
new Blog {FollowersCount=246, Name="GHI", Url="ghi.com" },
new Blog {FollowersCount=135, Name="JKL", Url="jkl.com" },
new Blog {FollowersCount=258, Name="MNO", Url="mno.com" }
};
blogs.ForEach(b => context.Blogs.Add(b));
context.SaveChanges();
}
}
Main Method:
static void Main(string[] args)
{
Database.SetInitializer(new DataInitializer());
using (var db = new BlogContext())
{
//db.Blogs.Add(new Blog { Name = "KOLP" });
//db.SaveChanges();
foreach (var blog in db.Blogs)
{
Console.WriteLine($"\n*****({blog.BlogId})*****");
Console.WriteLine("blog.Name: " + blog.Name);
}
}
Console.ReadLine();
}
To understand the role of DropCreateDatabaseAlways I deleted a property from this entity(Blog), and when I run the application, it throws this error:
There is already an object named 'Blogs' in the database.
Shouldn't it drop the database at any case, and then recreate it from the presented model?

Related

How do I implement "if exists update" with custom migration in EF Core?

I'm trying to create a migration for a new entity. Here is the thing, though: due to it being saved as an inner object for a different entity, I have no way to check if it exists (If it is, it needs to be updated).
Now, what I would like to have, is the ability to annotate the table (more specifically, the PK) so that if I try to add an entity that already exists, it will update it, instead of fail.
Is this possible? If so, how?
(here is a sample code that shows the issue).
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql(#"Host=localhost;Database=mydatabase3;Username=postgres;Password=1234");
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public Blog ContainerBlog { get; set; }
public int blabla { get; set; }
}
class Program
{
static void Main(string[] args)
{
Blog b1 = new Blog();
Blog b2 = new Blog();
b2.ContainerBlog = b1;
using (var ctx = new BloggingContext())
{
ctx.Database.Migrate();
ctx.Blogs.Add(b1);
ctx.SaveChanges();
}
using (var ctx = new BloggingContext())
{
ctx.Blogs.Add(b2);
ctx.SaveChanges();
}
}
}

Entity Framework Code First Seeding Data

I am using code first Approach in entity framework, but I am unable to seed the default data into the table. Please help.
Models
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public int Salary { get; set; }
public virtual Department Departments { get; set; }
}
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
public Department()
{
this.Employees = new List<Employee>();
}
}
Initializer
public class DepartmentInitializer : DropCreateDatabaseIfModelChanges<EmployeeDBContext>
{
protected override void Seed(EmployeeDBContext context)
{
IList<Department> lst = new List<Department>
{
new Department
{
Name = "Developer",
Location = "Bangalore"
},
new Department
{
Name = "Tester",
Location = "Bangalore"
},
new Department
{
Name = "IT Services",
Location = "Chennai"
}
};
foreach (var item in lst)
{
context.Departments.Add(item);
}
context.SaveChanges();
}
}
Main App
class Program
{
static void Main(string[] args)
{
using (var db = new EmployeeDBContext())
{
Database.SetInitializer<EmployeeDBContext>(new DepartmentInitializer());
}
}
}
For version 6 of Entity Framework, using 'migrations' is the preferred way to version the database, using the "Configuration.Seed" method as shown in this tutorial:
http://www.asp.net/web-api/overview/data/using-web-api-with-entity-framework/part-3
Have you tried running "Update-Database" from the Package Manager Console to get it to work?
I know I have had issues using the older seeding method with EF6. Migrations has also changed for Entity Framework Core 1 (formerly EF7), so make sure you are applying the correct technique to the correct version.
Try actually querying your db
On my machine, the seeder runs when I query it for the first time.
using (var db = new EmployeeDBContext())
{
Database.SetInitializer<EmployeeDBContext>(new DepartmentInitializer());
var depts = db.Departments.ToList();
}

Can not seed data with EF Code First

I found the problem, Solution is at comments.
I can create tables and diagram but I can not seed data to table.
1.I installed EF by Nuget.
2.From PM console I wrote Enable-Migrations –EnableAutomaticMigrations.
Model is in All.Model class library and and context methods are in All.Dal class library I did not understand what am I doing wrong can you help me?
This is my context code:
using All.Model;
namespace All.Dal
{
public class AllDb : DbContext
{
public AllDb()
{
Database.Connection.ConnectionString = "Server=SEUPHORIA;Database=AllDb;UID=sa;PWD=123;";
}
public DbSet<Category> Categories { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<Line> Lines { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<AllDb>(new DbStrategy());
modelBuilder.Entity<Category>().Property(c => c.Name).IsRequired();
modelBuilder.Entity<Comment>().Property(c => c.Letter).IsRequired();
}
}
}
And this is my strategy code:
using All.Model;
namespace All.Dal
{
public class DbStrategy : DropCreateDatabaseIfModelChanges<AllDb>
{
protected override void Seed(AllDb context)
{
List<Category> CategoryDefault = new List<Category>
{
new Category { Name="Organic", UpID = 0 },
new Category { Name="Object", UpID=0},
new Category { Name="Time",UpID=0},
};
foreach (Category item in CategoryDefault)
{
context.Categories.Add(item);
} context.Users.Add(new User { Name = "sss" });
}
}
}
this is my category class:
public class Category : Standart
{
public int UpID { get; set; }
public string Name { get; set; }
public int LineID { get; set; }
public virtual List<Line> Lines { get; set; }
}
You are adding the items into the DB context but are not committing the changes by calling SaveChanges() on them. Just add this one line:
protected override void Seed(AllDb context)
{
List<Category> CategoryDefault = new List<Category>
{
new Category { Name="Organic", UpID = 0 },
new Category { Name="Object", UpID=0},
new Category { Name="Time",UpID=0},
};
foreach (Category item in CategoryDefault)
{
context.Categories.Add(item);
}
context.Users.Add(new User { Name = "sss" });
context.SaveChanges(); // make sure you save!
}

Is this the way to implement a collection participating in and EF code first many to many relationship?

I have a situation where the code I've arrived at doesn't match any examples I find so I wonder if I'm missing something.
Basically, I want an EF code first Entity that contains a collection of Entities participating in a many-to-many relationship.
Then, I'd like to be able to:
Add to collection at the same time as creating an entity
Not get a warning about accessing a virtual member from constructor
Here's what I have:
public class NotificationUser
{
private ICollection<NotificationUserGroup> _userGroups = new HashSet<NotificationUserGroup>();
public int UserId { get; set; }
public string UserName { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<NotificationUserGroup> UserGroups
{
get { return _userGroups; }
set { _userGroups = value; }
}
}
Is there a better/different way to accomplish my goal?
This example might help
public class NotificationUser
{
public NotificationUser()
{
UserGroups = new HashSet<NotificationUserGroup>();
}
public int NotificationUserId { get; set; }
public string UserName { get; set; }
public bool IsActive { get; set; }
public virtual ICollection<NotificationUserGroup> UserGroups { get; set; }
}
public class NotificationUserGroup
{
public int NotificationUserGroupId { get; set; }
public string GroupName { get; set; }
}
public class Context : DbContext
{
public Context()
: base()
{
}
public DbSet<NotificationUser> NotificationUsers { get; set; }
public DbSet<NotificationUserGroup> NotificationUserGroup { get; set; }
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
using (var ctx = new Context())
{
var user = new NotificationUser() { UserName = "Name1" };
user.UserGroups.Add(new NotificationUserGroup() { GroupName = "Group1" });
user.UserGroups.Add(new NotificationUserGroup() { GroupName = "Group2" });
ctx.NotificationUsers.Add(user);
ctx.SaveChanges();
}
using (var ctx = new Context())
{
foreach (var user in ctx.NotificationUsers)
{
foreach (var group in user.UserGroups)
Console.WriteLine("Group Id: {0}, Group Name: {1}, UserName: {2}", group.NotificationUserGroupId, group.GroupName,user.UserName);
}
foreach (var group in ctx.NotificationUserGroup)
{
Console.WriteLine("Group Id: {0}, Group Name: {1}", group.NotificationUserGroupId, group.GroupName);
}
}
Console.ReadKey();
}
}

Entity Framework: Split table into multiple tables

I have the following table [PaymentComponent] created using following EF code first approach (TPH inheritance). It works fine. I need to change the database design – need to store GiftCouponPayments in GiftCouponPayment table and ClubCardPayments in ClubCardPayment table. What change need to be done in C# code to get the required database structure?
CODE
public abstract class PaymentComponent
{
public int PaymentComponentID { get; set; }
public int MyValue { get; set; }
public string MyType { get; set; }
public abstract int GetEffectiveValue();
}
public partial class GiftCouponPayment : PaymentComponent
{
public override int GetEffectiveValue()
{
if (MyValue < 2000)
{
return 0;
}
return MyValue;
}
}
public partial class ClubCardPayment : PaymentComponent
{
public override int GetEffectiveValue()
{
return MyValue;
}
}
public partial class Payment
{
public int PaymentID { get; set; }
public List<PaymentComponent> PaymentComponents { get; set; }
public DateTime PayedTime { get; set; }
}
//System.Data.Entity.DbContext is from EntityFramework.dll
public class NerdDinners : System.Data.Entity.DbContext
{
public NerdDinners(string connString): base(connString)
{
}
protected override void OnModelCreating(DbModelBuilder modelbuilder)
{
modelbuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
public DbSet<GiftCouponPayment> GiftCouponPayments { get; set; }
public DbSet<ClubCardPayment> ClubCardPayments { get; set; }
public DbSet<Payment> Payments { get; set; }
}
CLIENT
static void Main(string[] args)
{
string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30";
using (var db = new NerdDinners(connectionstring))
{
GiftCouponPayment giftCouponPayment = new GiftCouponPayment();
giftCouponPayment.MyValue=250;
giftCouponPayment.MyType = "GiftCouponPayment";
ClubCardPayment clubCardPayment = new ClubCardPayment();
clubCardPayment.MyValue = 5000;
clubCardPayment.MyType = "ClubCardPayment";
List<PaymentComponent> comps = new List<PaymentComponent>();
comps.Add(giftCouponPayment);
comps.Add(clubCardPayment);
var payment = new Payment { PaymentComponents = comps, PayedTime=DateTime.Now };
db.Payments.Add(payment);
int recordsAffected = db.SaveChanges();
}
}
REFERENCE:
How do I get Entity Framework 4.3 Code First to map a subclass using Table Per Type (TPT)?
http://weblogs.asp.net/manavi/archive/2011/04/24/associations-in-ef-4-1-code-first-part-4-table-splitting.aspx
http://www.robbagby.com/entity-framework/entity-framework-modeling-entity-splitting/
Entity Framework Mapping Scenarios - http://msdn.microsoft.com/en-us/library/cc716779.aspx
http://blogs.microsoft.co.il/blogs/gilf/archive/2009/03/06/entity-splitting-in-entity-framework.aspx
In your Context class in OnModelCreating:
modelBuilder.Entity<GiftCouponPayment>()
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("GiftCouponPayment");
});
modelBuilder.Entity<ClubCardPayment>()
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("ClubCardPayment");
});

Categories