Entity Framework Database First Classes and Table Names - entity-framework-6

I am trying to add .edmx to my web api application. The table names in our database are long and cumbersome like tbl_Company, tbl_User_Logins, tbl_Company_Departments. I would like to use neat class names like Company, User, Departments that map to these tables. I have been trying to find sample code to do this, but I feel like I am not "asking the right questions" which is why I can't find any answer.
I tried creating classes for "Department" and "User", and I tried adding code like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Department>().ToTable("tbl_Company_Departments_xlu");
modelBuilder.Entity<User>().ToTable("tbl_User_Logins");
}
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Department> Departments { get; set; }
but it didn't work when I tried to add a new department using Departments.Add(department). I am obviously missing a step, but I do not know what it is. I am new to this and am struggling. Any assistance is greatly appreciated.

Related

asp.net mvc enable on delete cascade for entire project

I've searched for something that solves my problem, but don't seem to find anything.
Is there a way to simply enable OnDeleteCascade for the entire project?
Can anyone help please?
You want to setup your relationships in your DbContext and specify your cascade deletes in your model builder.
public class SomeContext : DbContext
{
public DbSet<EntityOne> EntityOnes { get; set; }
public DbSet<EntityTwo> EntityTwos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EntityOne>()
.HasRequired(d => d.EntityTwo)
.WillCascadeOnDelete(true); // this is what you want to do
}
}
Reference: https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application
Reference (This one is really good for various relationships): https://msdn.microsoft.com/en-us/library/jj591620(v=vs.113).aspx
EDIT: Wanted to note this is called Entity Framework Fluent API if you wanted to google for some more info.

Why need use OnModelCreating (MVC 5 EF code first)?

I don't understand what is the reason of using OnModelCreating function?
when I can do something like
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Int Id { get; set; }
public Int LanguageId { get; set; }
[ForeignKey("LanguageId")]
public Language Language { get; set; }
Maybe I am wrong but when I reads about this,it is explained as it's for Many-to-Many relationship.
so why not do something like this.
ICollection<User> Users
For making relationship between entities, we have two options
DataAnnotation (Which you are using)
Fluent API.
When we are using fluent API we need to specify our relationship in this OnModelCreating(DbModelbuilder modelbuilder) method.So when model is created first time they should maintain relationship between entities.
Common Example for using this method is given in this below code snnipet
modelBuilder.Entity<Department>().Property(t => t.Name).HasMaxLength(50);
the same can be achieved using data annotation attribute.
[MaxLength(50)]
public string Name {get;set;}
So if you dont want to use DataAnotation Use Fluent API to serve your purpose.

Add new table to an existing database using Code First approach in EF 6 and MVC 5

I know this should be simple, but I was unable to find correct tutorial or explanation on web on this subject. There is a lot of videos and posts about adding new column to an existing table, using code first approach, but I can not find any with step by step explanation on how to add whole new table into existing database.
Which is weird, I was pretty sure that I will find many examples. Maybe my search criteria is bad. So if anybody has any good link or video, please share.
What I'm trying to do is to add table Post into existing Default Database, created by MVC 5 project.
I've made model class first, named it Post and it has a simple definition:
public class Post
{
[Key]
public int PostId { get; set; }
public string PostText { get; set; }
public byte[] ImagePost { get; set; }
public byte[] FilePost { get; set; }
public string TextPost { get; set; }
public string UserId { get; set; }
}
Then I have first doubts. I know I should create DbContext, but if I want to hit an existing database, should I use existing DbContext, already created by default in Web.config file like this:
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-StudentBookApp-20150114035149.mdf;Initial Catalog=aspnet-StudentBookApp-20150114035149;Integrated Security=True"
providerName="System.Data.SqlClient" />
Or I should use all new DbContext created for Post class?
Anyhow I've tried it both, but no success. When I created this new context I was doing following in PMC:
Enable-Migrations
Add-Migration "PostMigration"
Update-Database
Usually, or all goes well, but I don't get any new table in database, or I get an error: AspNetUsers already exists, and AspNetUsers is one of auto-created tables that I've changed by adding new columns to it.
Update: My context right now is in seperated class named PostContext and it looks like this:
public class PostContext : DbContext
{
public PostContext() : base("name=PostContext")
{
}
public DbSet<Post> Posts { get; set; }
}
Second try:
Since my first approach didn't gave any result. I've tried doing what's described in this link. Adding mapping to my project:
I've crated new class PostConfiguration for mapping:
public class PostConfiguration : EntityTypeConfiguration<Post>
{
public PostConfiguration() : base()
{
HasKey(p => p.PostId);
ToTable("Post");
HasOptional(p => p.PostText);
ToTable("Post");
HasOptional(p => p.ImagePost);
ToTable("Post");
HasOptional(p => p.TextPost);
ToTable("Post");
HasOptional(p => p.FilePost);
ToTable("Post");
HasRequired(p => p.UserId);
ToTable("Post");
}
}
In the class Post I've added context class too PostContext with modelBuilder variable as they've suggested in listed link above:
public class PostContext : DbContext
{
static PostContext()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<PostContext>());
}
public DbSet<Post> Posts { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Properties()
.Where(p => p.Name == "Key")
.Configure(p => p.IsKey());
modelBuilder.Configurations.Add(new PostConfiguration());
}
}
I've run all PMC commands again, and still no success, table Post is missing from default database.
What has happened here is that you had existing database tables before Migrations where enabled.
So Entity Framework thinks that ALL your database objects need to created, this could be seen by opening up your PostMigration migration file.
The best way is to trick EF into to doing the initial migration with every before you added the Post table and then do the Posts migration after.
Steps
Comment out the Posts in the DBContext so EF doesn't know about posts
//public DbSet<Post> Posts { get; set; }
Enable Migrations
Enable-Migrations
Add an initial migration with all tables prior to your changes
Add-Migration "InitialBaseline" –IgnoreChanges
Now update the database, this will create a MigrationHistory table so that EF knows what migrations have been run.
Update-Database
Now you can uncomment the line in 1 to "Do your change"
Create a new migration with the addition of Posts
Add-Migration "PostMigration"
Now do an update... and hopefully it should all work.
Update-Database
Now that migrations are all setup and they are baselined future migrations will be easy.
For more information I found this link useful:
http://msdn.microsoft.com/en-us/data/dn579398.aspx
You can resolve that by going to migration folder and delete Post-Migration file, then inside migration folder you will find a file named ApplicationContextModelSnapshot or something like that, then delete modelBuilder.Entity related to your post model.
After that do:
Add-Migration "PostMigration"
Update-Database

What is the best way to use migrations with MVC5 and .Net Identity?

I'm just putting myself through the paces learning MVC5 with EF6 and Code First and have run into some confusion...
How are people managing their DbSets with the Identity changes, especially with Migrations?
Are you managing two sets of Migrations or putting your normal DbSets into the IdentityModel.cs file?
This is what I have currently:
public class ApplicationUser : IdentityUser
{
}
public class AoecContext : IdentityDbContext
{
public AoecContext()
: base("DefaultConnection")
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Faculty> People { get; set; }
public DbSet<SitePage> SitePages { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<SitePage>().HasOptional(p => p.CourseDetails);
}
}
Is that a good idea, or just plain bad?
Your concerns are a bit better separated if you keep your IdentityDbContext separate from your DomainDbContext, but then you would need to manage two sets of migrations (among other things). As you have it you'll only need one set of migrations. I wouldn't consider what you're doing "bad" necessarily- it really depends on the project.
If its any consolation, the project that we are currently working on uses only one DbContext that also inherits from IdentityDbContext as yours does. It does pull in some references to the Data Access project that I wish weren't there, but it does greatly simplify working with EF in terms of database generation, persistence, and migrations. Whether we'll outgrow it in the future or not is hard to say.

EF Code First: How do I make a virtual collection private while still having it correctly create my database model?

I am using Code First to automatically generate my database, and this works perfectly, generating an Orders table and an OrderLines table as expected when I add some test data.
I have the following Order class:
public class Order
{
public int OrderID { get; set; }
public void AddItem(string productCode, int quantity)
{
var existingLine = OrderLines.FirstOrDefault(x => x.ProductOption.ProductCode == item.ProductCode);
if (existingLine == null)
OrderLines.Add(new OrderLine { ProductOption = item, Quantity = quantity });
else
existingLine.Quantity += quantity;
}
public void RemoveItem(string productCode)
{
OrderLines.Remove(OrderLines.Where(x => x.ProductOption.ProductCode == productCode).FirstOrDefault());
}
public virtual ICollection<OrderLine> OrderLines { get; set; }
public Order()
{
OrderLines = new List<OrderLine>();
}
}
What I really want is to encapsulate the OrderLines collection, making it impossible for consumers of the class to directly add and remove items to/from it (using the Add / Remove methods of ICollection) and instead forcing them to use my custom AddItem and RemoveItem methods.
Normally I could just make the collection private, but I can't do that because it needs to be virtual for EF to correctly create the OrderLines table/foreign keys.
This answer seems to suggest that making the property internal would do the trick, but I tried, and in that case no OrderLines table is created.
Is there any way that this can be accomplished, or should I have designed this differently somehow? Any help much appreciated!
Update
After a bit more searching, I found this question which is rather more clearly stated than mine; however, it's still unanswered. The poster does link to this post which seems to suggest it can't really be done in the way I'm thinking of, but does anyone have any more up-to-date information?
I don't know if it's possible to do what you are asking or not, but I'm not sure it's the best design. The problem that I am seeing is you are firmly integrating your business logic into your business entities, and I think this will turn into confusion down the road.
Take the following scenario under consideration. Say you have a new requirement where you want users to be able to remove all items from an order. The only way to do it with your entity is to create a new RemoveAllItems() method to your Order class which does that. Now say you have a new requirement to Remove all items from an order that are in a specific category. That then means that you have to add yet another method.
This causes really bloated classes, and there is one major issue you will come up with. If you (or another developer) want to look at an entity and determine it's data structure, you can't at a glance because it's so intertwined with business logic.
What I would suggest is that you keep your entities as pure data structures, keeping all their relationships public. Then you need to create a service layer, which can consist of small or big classes (however you want to organize them) that actually perform the business functions. So for example, you can have a OrderItemService class, which has methods for adding, editing, and removing items from an order. All your business logic is performed in this class, and you just have to enforce that only service classes are allowed to interact with db entities.
Now, if you are looking for how a particular business process is performed, you know to look in the service layer classes, and if you want to look at how a data structure or entity is organized, you look at the entity. This keeps everything clean and very mantainable.
I'm far from an expert on code first and I haven't tried the following but is it possible to use the ReadOnlyCollectionBase and create a read only list similar to this MSDN article?
Well what you can do is set your collection as private and make the relationship using fluent API in the OnModelCreating, as shown below, I don't know if this will work, just make a try:
public class YourContext : DbContext
{
public DbSet<Order> Orders { get; set; }
public DbSet<OrderLine> OrderLines { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.HasMany(o => o.OrderLines)
.WithRequired(l => l.OrderId)
.HasForeignKey(l => l.OrderId);
}
}
This will make your OrderLines as readonly:
public class YourContext : DbContext
{
public DbSet<Order> Orders { get; set; }
public DbSet<OrderLine> OrderLines
{
get { return set<OrderLine>(); }
}
}
I hope this can help you, please take a look a this blog post: EF Feature CTP5: Fluent API Samples

Resources