Looking way to create a relationship between entities - c#

I have two entities one is employee and other one is project and i am looking to store the list of all bookmarked project ID's in employee entity and one employee can add bookmarks to multiple projects. One project can be bookmarked by multiple employees as well.
The employee entity structure is like this
public class Employee
{
[Key]
public int Id { get; set; }
public string Email { get; set; }
public string DisplayName { get; set; }
public List<Section> OwnedSections { get; set; } = new List<Section>();
public List<string> BookmarkProjectsIDs { get; set; } // just specified the list of bookmark projectID's
}
and the below is the project entity structure
public class Project
{
[Key, GraphQLNonNullType]
public string ProjectNumber { get; set; }
public string Name { get; set; }
[Column(TypeName = "jsonb")]
public ProjectSectionStatus SectionStatuses { get; set; } = new ProjectSectionStatus();
}
Is this is right way to specify or is there any way we can specify just to store the ID's of projects and at the same time i do not want to duplicate the data as well. I am using Entity framework core with .Net core.
many thanks in advance.

Related

EF model change one-to-one relationship to many-to-many relationship

I have two tables with one-to-one relationship.
public class Name
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Category { get; set; }
public int? NameId { get; set; }
[ForeignKey("NameId ")]
public virtual Name Name { get; set; }
}
I already have data in those tables.
I know the database relations are not supported to be changed.
Is it possible to change one-to-one relationships to many-to-many relationships?
What is the most suitable approach to overcome this requirement?
Yes, you can still change that, using migrations.
Step 1 is to create a linking table, like NameCategories, which looks something like this:
public class NameCategories
{
public int Id { get; set; }
public int NameId { get; set; }
public Name Name { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
Step 2 is to reference this table in the tables you already have. In Name it would look like this
public class Name
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<NameCategory> Categories { get; set; }
}
Step 3 is to add a migration. You'll have some AddColumn() and some DropColumn() statements. In between them, when all the add stuff was executed but the drops not yet, you can add SQL code to carry over all the existing relations into the newly created table. After that, the old data will be deleted by the DropColumn() code. In your example, this would look something like this
INSERT INTO NameCategories (NameId, CategoryId)
SELECT (n.Id, c.Id) FROM Names n
JOIN Categories c on c.NameId = n.Id
WHERE ..
You can execute the SQL in the migration like this:
var sql = #"...";
Sql(sql);
I hope this helps you out!

Modeling a one-to many relationship- Model vs ViewModel

I am currently trying to model an object class with a one-to-many relationship with another object in Model-First MVC- a "Contact" object that includes, among other things, a list of (references to?) one or more "Interests", chosen upon creation of a Contact from the full database list of Interests. It is my understanding that one uses a ViewModel to accommodate such a relationship, but I think I am misunderstanding what does or does not go in the model vs the viewModel.
At present, I have a Contacts model:
public class Contact
{
public int Id { get; set; }
public string Email { get; set; }
public virtual List<Interest> Interests { get; set; }
public List<int> InterestIds { get; set; }
}
An Interest model:
public class Interest
{
public int Id { get; set; }
public string Name { get; set; }
}
A Contact viewModel:
public class ContactViewModel
{
public int Id { get; set; }
public string Email { get; set; }
public List<int> InterestIds { get; set; }
public List<InterestViewModel> Interests { get; set; }
}
And an Interest viewModel
public class ContactViewModel
{
public int Id { get; set; }
public string Email { get; set; }
public List<int> InterestIds { get; set; }
public List<InterestViewModel> Interests { get; set; }
}
But I'm getting conflicted accounts of what goes where.
In short, I intend the end result that I should be able to choose one or more Interests (preferably with a series of checkboxes) from the Create view to be stored in the new Contact, and then from the Index view be able to filter the table of Contacts by which Interests they do or do not have. I have logic planned out for most of that already, but for the time being how should I design my Models vs my ViewModels in order to best accommodate this vision?
your Contact entity has a logical error, you should remove InterestIds property from Contact entity and add a property with name ContactId to your Interest entity. it provides foreign key for contact(one to many relation from Contact to Interest). however if ViewModel is equals to the Model, so you don't need any ViewModel.

Entity Framework: how to solve table in table

I'm testing the following scenario (code below): create a shopping mall, with shops, with cashiers, with cash desks and persons operating it.
So I've created the following classes
Table Mall
Table Shop
Table CashDesk
Table Person
Basic classes with an ID and a name.
Then I need a derived class from Person being PersonCashier or PersonCustomer.
Since everything is related, I need to create intersection tables for the many to many scenarios.
I've created the following intersection tables:
The Mall contains shops: MallShop
The shop contains CashDesks: MallShopCashDesk
And the CashDesk containing cashiers: MallShopCashDeskPersonCashier
This just doesnt feel right. Can anyone help me out on a best practice
public class Mall
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
[Required]
public int NumberOfShopSpaces { get; set; }
}
public class Shop
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
}
public class CashDesk
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class Person
{
public int Id { get; set; }
[Required]
public string FullName { get; set; }
[Required]
public string Gender { get; set; }
}
public class PersonCashier : Person
{
[Required]
public int ShopId { get; set; }
public virtual Shop Shop { get; set; }
}
These are the base classes. How should i add a shop to a mall, a cashdesk to a shop, and a cashier to a cashdesk? (i've tried alot but posting the code would make the question look like spaghetti)
If this is code first then EF will make the relationship tables for you. You just need to add the relationships in your classes.
Exactly what they should be is not clear from your description because it depends on what relationships you want; if you want a many-many between PersonCashier and CashDesk it would be like this:
public class CashDesk
{
public List<PersonCashier> Cashiers { get; set; }
}
public class PersonCashier : Person
{
public List<CashDesk> CashDesks { get; set; }
}
(not showing all the fields for brevity)
public class Mall
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
[Required]
public int NumberOfShopSpaces { get; set; }
List<Shop> CurrentShops { get; set; }
}
public class Shop
{
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; }
public List<CashDesk> CashDesks { get;set; }
}
I added the list of shops to the Mall class and CashDesks to Shops. This gives you a list of shops in the mall, and a list of cashdesks in each shop and you can follow this method for everything else you need.
If you have a database, you will have a Mall table and a Shop table.
The Shop table can have a Foreign Key to the Mall table, that's how you link them and this will work with the class structure at the top.
Or, you can have another table called MallShops where you have 2 fields, one being the MallID, the other the ShopID. This is called a Link table.
Both approaches will work with the second allowing a more complex structure with lots of Malls linked to Lots of Shops.
I would start with the database structure first, make sure you cover all you need, then you can do the classes etc in a way that makes sense. If you use something like EntityFramework then it will create all the classes for you once your database structure is ready.

Entity Framework DB-First, implement inheritance

I'm trying to implement inheritance using entity framework 6.0 and database first approach. OK, let's say I have a Person and an Organization entity like below:
// a simplified version of organization entity
public class Organization
{
public Guid ID { get; set; }
public string Nickname { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string OfficialName { get; set; }
public Guid CEOID { get; set; }
public DateTime? RegisterDate { get; set; }
}
// a simplified version of person entity
public class Person
{
public Guid ID { get; set; }
public string Nickname { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public Guid PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string NationalCode { get; set; }
public DateTime? BirthDate { get; set; }
}
I can create these two tables in database, but I want to use inheritance so the fields which is repeated in both Person and Organization could be in another base class like below:
public class Identity
{
// These fields are the common fields between Person and Organization
public Guid ID { get; set; }
public string Nickname { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
}
How can I achieve this in db-first approach?
One possible way is to use one table for each type called TPT (table-per-type), which I prefer to use. To achieve this, you define your tables like the model shown in the following picture:
Note that the relationships between child and base entity are one-to-one on their pk columns, and all common fields are moved to the base table. After creating your tables, right click on the models page in your visual studio, and select Update Model from Database..., and then in the add tab, select these 3 tables to add. At first you should see this model diagram, which needs to be changed a bit:
Do these steps for Person and Organization separately:
Right click on entity and select Properties
In the Base Type property select Identity
Select and then delete the association between this entity and Identity
Select and then Delete the PK (ID column) of this entity (Inherits from base entity)
After these steps save your model. Now your model should look like this:
Now compile your project and enjoy your life!
Additional resources:
Entity Framework Designer TPH Inheritance

Using ICollection with MVC & Entity framework

Hi I'm learning to use MVc using Code first method. I'm having trouble understanding the use of ICollection<> with my setup. I have two classes/entitys: 'Restaurant' & 'RestaurantReview' as below:
public class Restaurant
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
public string Country { get; set; }
public ICollection<RestaurantReview> Reviews { get; set; }
}
and.....
public class RestaurantReview
{
public int Id { get; set; }
public int Rating { get; set; }
public string Body { get; set; }
public string ReviewerName { get; set; }
public int RestaurantId { get; set; }
}
now whats confusing me is the last property of the Restaurant class. Why is it of type 'ICollection' and uses my RestaurantReview class as a parameter, what does it do, hope I
have made myself clear
It's a definition of one to many relationship.
With that property (sometimes called Navigation Property) Entity Framework will be able to connect Review with Restaurant it was written about. It will also allow you to get Review entities for given Restaurant entity really easily.
You can also remove public int RestaurantId { get; set; } from RestaurantReview class - That column is gonna be generated automatically by EF because of ICollection<RestaurantReview> in Restaurant class.

Categories