I am creating a fairly simplistic Database for a holiday system.
Entities
Employee
public class Employee
{
public int Id { get; set;}
public string Username { get; set; }
public LineManger Manager { get; set; }
}
LineManger
public class LineManager : Employee
{
public string CompanySection { get; set; }
}
Relationship
As you can see, each employee has one LineManger however an Employee could be a LineManager.
In my DbContext I have:
public DbSet<Employee> Employees { get; set; }
public DbSet<LineManager> Managers { get; set; }
public DbSet<HolidayConfiguration> Configurations { get; set; }
public DbSet<Holiday> Holidays { get; set; }
When I ran PM > Update-Database -verbose for the first time it only created an Employee table and this table has CompanySection and Manager_Id which doesn't map to anywhere seeing as there isn't a LineManager table.
Any explanations on why this has happened? Is this correct?
It has to be like this, because every LineManager is an Employee, so when you are querying Employees you are also looking for LineManager. DbSet<Employee> Employees matches only one table, so the only way how EF can create table is to put in it all fields from LineManager.
Sometime (when you have more inhertiance) EF create special column in which it puts class name.
Related
I am trying to build an organization hierarchy where each team might contain one or many members and/or one or many sub-teams.
To do so, my model is:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Members { get; set; }
public virtual ICollection<Team> SubTeams { get; set; }
public Employee Manager { get; set; }
}
When adding a migration and updating database, everything seems logical in the table.
EF has added an extra nullable column "Team_Id" where the Id of the parent Team gets stored.
My question is about getting the Id of the parent Team from my model.
I tried adding:
public int? Team_Id
To my model, but EF considered it as a model change and asked for another migration.
How can I get the value of column Team_Id in my model? getting this info takes too much processing when looping through teams.
I always add foreign key in my model. When it adds to the model, EF won't add Team_Id .
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Members { get; set; }
public virtual ICollection<Team> SubTeams { get; set; }
public Employee Manager { get; set; }
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public Team ParentTeam { get; set; }
}
I hope this example be helpful.
I am new to ASP.NET MVC. Using Entity Framework 6, I am working on a project to store employee skills in a database. The user can enter a new skill into a list of skills. I would like to keep track of who added the new skill. I have a table of all of the employees.
These are the models for the two tables.
public partial class Skill
{
public int ID { get; set; }
public string Skill { get; set; }
[ScaffoldColumn(false)]
public int LastActionUserID { get; set; }
public virtual Employee Employees { get; set; }
}
public partial class Employee
{
public int ID { get; set; }
public string EmployeeLAN { get; set; }
public int LastActionUserID { get; set; }
public virtual Employee Employees { get; set; }//References itself for LastActionUserID
public virtual ICollection<Skill> Skills{ get; set; } //Omitted in initial question
}
There is a 1 to Many mapping of Employee to Skill. I can get the current user's EmployeeLAN but how do I get the id of that Employee record to put into the Skill table automatically when then new skill is created? Must I convert the table to an enumerable object and use SingleOrDefault or LINQ? Or is there an easier way using EF6? Also, setting this automatically when a new skill is created would be done in the controller, correct?
You're on the right track and you should continue to use EF6.
The Employee class should have a Skills list. That way you can call myEmployee.Skills and have a list of all the skills available.
public partial class Employee
{
public int ID { get; set; }
public string EmployeeLAN { get; set; }
public int LastActionUserID { get; set; }
public virtual ICollection<Skill> Skills{ get; set; }
}
Also, setting this automatically when a new skill is created would be done in the controller, correct?
You'll need to add to the Skills list, call AddOrUpdate() to mark this as changed, then SaveChanges() to persist it to the database.
I recommend learning more from the MSDN docs and Julie Learman's
Entity Framework videos on Pluralsight
Here are the business requirements, in short:
All employees need to be stored in a database
Some employees have assistants, some do not
Some employees have more than one assistant
Assistants are employees, as well
There is obviously a bit of a self-referencing situation. But the difference from a typical "Employee-Manager" situation is that here one Employee can have 0 or multiple assistants. So, the combination of Employee and employee's Assistants needs to be stored in a separate table in a one-to-many relationship between Employee and EmployeeAssistant. But I'm getting confused how to model this in Entity Framework 6 Code First.
I started with this:
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class EmployeeAssistant
{
[ForeignKey("Employee")]
public int EmployeeId { get; set; }
public virtual Employee Employee { get; set; }
[ForeignKey("Assistant")]
public int AssistantId { get; set; }
public virtual Employee Assistant { get; set; }
}
But I get an error during Update-Database command:
Introducing FOREIGN KEY constraint 'FK_dbo.EmployeeAssistant_dbo.Employee_EmployeeId' on table 'EmployeeAssistant' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
What am I missing? Should I approach this differently?
since each employee may have one or more assistants (and each assistant will have one or more employees) and all are employees, the simplest solution is one class with two collections for assistants and employees, and the relations will be managed by the framework:
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<Employee> Assistants { get; set; }
public ICollection<Employee> Employees { get; set; }
}
when you use package manager console to add migration it will automatically create two tables, one for employees, and another for many to many relations.
then all you have to do is to find related assistants and/or employees by using Include extension method.
db.Employees.Where(x=>x.Id==id).Include(x=>x.Assistants).FirstOrDefault()
and/or
db.Employees.Where(x=>x.Id==id).Include(x=>x.Employees).FirstOrDefault()
Based on this link Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?
It seems if you delete an EmployeeAssistant with your code, it causes two cascading delete paths.
I would suggest a structure such as this:
After edit
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<EmployeeAssistant> Assistants { get; set; } //if an employee has no assistants this List can easily just be empty
OR
public ICollection<EmployeeAssistant> Assistants { get; set; } // depending on your architecture, choose the one that would suit you better
}
public class EmployeeAssistant
{
[ForeignKey("Employee")]
public int EmployeeId { get; set; } //this is the employee who 'has' this assistant
public virtual Employee Employee { get; set; }
public int Id { get; set; } //this is the assistant's own information - identical to employee's basic info
public string FirstName { get; set; }
public string LastName { get; set; }
}
After a while of brain-boggling, I even came up with a possibility where you just need 1 class, Employee, but it includes a bool IsAssistant denoting if this employee is an assistant, and AssistantEmployeeId which is an employee ID of the employee who 'has' this assistant.
For example:
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsAssistant { get; set; }
public int EmployeeAssistantID { get; set; }
}
I know this second method is very messy and probably doesn't suit your needs, but personally I always create database tables first then do 'Generate Model from Database' so I'm inexperienced at code-first approach.
I have a Vacation and a list of Countries. I whish to bind these together using a many-to-many relationship. I have a code-first Vacations model and Countries model. Both the individual tables aswell as the join table are successfully generated.
However, when I try to add a country to a vacation (or vice versa) the join table remains empty. I am able to successfully add the individual vacations aswell as the countries.
Models
public class Vacations
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int VacationId { get; set; }
public string ProductId { get; set; }
public string Name { get; set; }
public string Price { get; set; }
public virtual ICollection<Countries> Countries { get; set; }
public Vacations()
{
Countries = new List<Countries>();
}
}
public class Countries
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CountryID { get; set; }
public string CountryName { get; set; }
public virtual ICollection<Vacations> Vacations { get; set; }
public Countries()
{
Vacations = new List<Vacations>();
}
}
public class MyContext : DbContext
{
public MyContext()
: base("myconn")
{
}
public DbSet<Vacations> Vacations { get; set; }
public DbSet<Countries> Countries { get; set; }
}
Insert the Vacation
Vacations vacation = database.Vacations.Add(new Vacations
{
Name = vacationData.Name,
Description = vacationData.Description,
});
database.SaveChanges();
// to make sure the key is in the database to refrence
foreach (string country in AllMyCountries)
{
Countries countries = database.Countries.Add(new Countries
{
CountryName = country
});
countries.Vacations.Add(vacation);
vacation.Countries.Add(countries);
}
database.SaveChanges();
I have also tried just adding to one entity, and adding more calls to SaveChanges() inbetween.
Interesting problem in that your sample code all looks perfectly okay. Infact, I put a quick test together around this code and Entity Framework created the mapping table vacationscountries as expected and populated it correctly.
Just on the off-change, can you confirm that you are looking in the mapping table created by Entity Framework and not a custom mapping table? The only reason I mention it is that theres no way (that I know of) to map a many-to-many relationship to a custom junction table using Data Annotations.
If thats not the case, then the next thing I would do is to trace out the sql being generated by Entity Framework - either using your native database tracing tooling (e.g. Sql Profiler), a third party tool like EFProf, or through a logging interceptor ( http://msdn.microsoft.com/en-gb/data/dn469464.aspx ). Hopefully that will give some lower-level insights into the problem.
I re-created your Models but made some adjustments that generate the same results. I manually created the junction table VacationsCountries with the following code:
public class VacationsCountries
{
[Key, Column(Order = 0)]
public int VacationId { get; set; }
public virtual Vacations Vacation { get; set; }
[Key, Column(Order = 1)]
public int CountryId { get; set; }
public virtual Countries Country { get; set; }
}
I also added this line of code to the MyContext class:
public DbSet<VacationsCountries> VacationsCountries { get; set; }
Instead of using:
countries.Vacations.Add(vacation);
vacation.Countries.Add(countries);
I use:
VacationsCountries vc = database.VacationsCountries.Add(new VacationsCountries
{
Country = countries,
Vacation = vacation
});
and then call database.SaveChanges();
I checked the database and the entries were added to the VacationsCountries table.
Goal. I have a "Gift" entity that describes what someone has to offer (babysitting, dog walking, etc) with a rating. And I want a "GiftCategory" entity that gives general category descriptive information (pets, sports, automotive, etc) for someone to search apon and then get all gift that have those categories. A "Gift" entity can have multiple "GiftCategory" entities associated with it. I want the ability to search for a category and pull out all "Gift" entities that have been created with those categories associated with them. Here is what I have so far but it doesn't seem to work with the entity first approach. Maybe I need another table that connects the two entities because currently the way the two tables are connected doesn't seem correct?
Gift entity:
public class Gift
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<GiftCategory> Categories { get; set; } // is this incorrect???
public int Rating { get; set; }
}
Category entity:
public class GiftCategory
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The "GiftCategory" table that gets created creates a gift_id column that links the "GiftCategory" back to a gift (not what I want)!!!!
It seems like I would need to create a entity that connects the two entities? Something like:
public class ConnectGifts
{
public int Id { get; set; }
public string GiftId{ get; set; }
public string GiftCategoryID{ get; set; }
}
This way I can have multiple categories for a Gift, but the thing I don't understand is with entity first I really don't need this entity I just need what would be this table to get/query the "GiftCategory" entities for ids then get the gift ids to get all the gifts. So it seems like creating this entity is overkill? Is there a way to do it without creating a third table/entity ("ConnectGifts") with code first? Or am I not understanding that all entities are tables and all tables are entities? I'm also using linq-to-sql for all querying.
You're looking for a many-to-many relationship and can be defined as:
public class Gift
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<GiftCategory> Categories { get; set; } // is this incorrect???
public int Rating { get; set; }
}
public class GiftCategory
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Gift> Gifts { get; set; }
}
So each has a collection of the other. Gift has many Categories and Category had many Gifts. You could use a bridge table like you've done with ConnectGifts but it's not necessary with EF. Using just Gift and GiftCategory, EF will actually create the bridge table for you.