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
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();
}
}
}
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();
}
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!
}
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();
}
}
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");
});