EF Code First access child of child to set ForeignKey - ef-code-first

Below are the sample classes
public class Parent {
public int ParentId {get; set;}
public string UserName {get; set;}
public Child Child{get; set;}
}
public class Child {
public Child1[] ListChild1 {get; set;}
}
public class Child1 {
public int Child1Id {get; set;}
public int ParentId {get; set;}
public int Child1Name {get;set;}
}
Need to create the table using Entity Framework Code-First approach. ParentId is PK in Parent and FK in Child1. No need to create
table for Child class. Child1 table has Child1Id as PK and ParentId as FK. Need some help how to create this relationship in database
using fluent api.
Required Databse structure
Parent
ParentId (PK)
UserName
Child1
Child1Id (PK)
ParentId (FK)
ChildName

I have used something similar in the past :
public class Category
{
[Key]
public int ID { get; set; }
[Required]
public string Name { get; set; }
public int? ParentID { get; set; }
public virtual Category Parent { get; set; }
public virtual ICollection<Category> Children { get; set; }
}
This should work for an infinite parent, children relationship in the same table.

Related

ef core shared child table with one-to-many

I would like to have a shared table that can be somehow referenced to multiple parent tables. The parent tables can have multiple rows from the shared Attachement table. The Type/TypeId would be a column which points to the parent table (like if the parentId is in Person or Company table)
Shared table:
Id | ParentId | Type/TypeId | Value
1 1 Person/1 "somestringvalue"
2 1 Person/1 "another value"
3 3 Company/2 "value"
....
The models would look something like this
public class Attachement
{
[Key]
public int Id { get; set; }
//PK- Id of the parent table
public int ParentId { get; set; }
// type or enum of a parent table. Should point to which table it points to
public int Type { get; set; }
public string Value { get; set; }
}
public class Person
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
//shared table
public ICollection<Attachement> Attachements { get; set; }
}
public class Company
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
//shared table
public ICollection<Attachement> Attachements { get; set; }
}
Sidenote also - im using code first pattern.
Thanks!

Tree structure with reference to root in Entity Framework

I'm trying to model a tree structure for orders in Entity Framework. Right now I've go the following:
public class ProjectModel
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int CustomerId { get; set; }
public virtual List<ProjectNode> Nodes { get; set; }
}
public class ProjectNode
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public string Path { get; set; }
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public virtual List<ProjectNode> Children { get; set; }
}
What I need to be able to do is get a reference to the root ProjectModel at any level of ProjectNode in order to authorize a given user actually having permission to view and change the project which contains the ProjectNode.
public class ProjectNode {
public int ProjectId { get; set; } //<-- this
...
public class ProjectModel {
[Key]
public int Id { get; set; } //<-- containing the value of this
}
My question is whether its possible to have a theoretical ProjectId property populated at every level of the tree structure, or if I need to set it manually.
I had something working that at first blush appeared to allow this functionality, but upon further investigation only populated the ProjectId for ProjectNodes contained in the ProjectModel's Nodes property.
It seems to me like it would be super inefficient to recurse backwards through the structure to get to the root.
Credit due to #TestWell for this answer -
Apparently, all I needed to do for EF to automatically populate the ProjectId property on the ProjectNode was to change the name of the Id property in ProjectModel to ProjectId.
Unfortunately, this doesn't appear to work if I add a CustomerId property to the ProjectNode that I would like automatically populated from the property of the same name on the node's root ProjectModel, which I realized is the more efficient solution to what I'm trying to do.

How to tell entity framework code first to order the lazy loaded list

Suppose I have the Following class
public class Account
{
public int AccountID {get; set;}
public string AccountName {get; set;}
public Account Parent { get; set; }
public virtual List<Account> Children { get; set; }
}
and I loaded list of accounts in a specific orderBy clause. my question is how can I tell entity framework code first to order the Children in a specific order when he lazy load that List?

Entity Framework Code First create db from models

I am trying to use entity framework to build the database and I need some help with the models:
The models are: Company, Departments, Users, TaskType1, TaskType2, TaskType3
public class Company
{
public Company()
{
this.Departments = new HashSet<Department>();
}
public int Id { get; set;}
public string CompanyName { get; set;}
public string Address { get; set;}
public string Phone { get; set;}
public virtual ICollection<Department> Departments { get; set;}
}
public class Department
{
public Department()
{
this.Users = new HashSet<User>();
}
public int Id { get; set;}
public string Name { get; set;}
public virtual Company Company { get; set;}
public virtual ICollection<User> Users { get; set;}
}
public class User
{
public Company()
{
}
public int Id { get; set;}
public string UserName { get; set;}
public string FullName { get; set;}
public virtual Department Department { get; set;}
}
public class TaskType1
{
public TaskType1()
{
}
public int Id { get; set;}
public string Name { get; set;}
public string Description { get; set;}
public int Priority { get; set;}
}
public class TaskType2
{
public TaskType2()
{
}
public int Id { get; set;}
public string Name { get; set;}
public string Description { get; set;}
public int Priority { get; set;}
public double EstimatedCosts { get; set;}
}
public class TaskType3
{
public TaskType3()
{
}
public int Id { get; set;}
public string Name { get; set;}
public string Description { get; set;}
public int Priority { get; set;}
public bool IsDone { get; set;}
}
the reason I need to have TaskType1, TaskType2, TaskType3 as tables is because there are different types of tasks (different data/fields is needed).
How can I connect my task types to the Company and to the Department and Users so I can get results like:
all tasks per company X
all tasks assigned to department z from company x
all tasks assigned to user w from department z from company x
P.S. The task types have common and different columns
You need to establish relationships between your models. For example, to get all tasks per company X, you would need a companyID column in each of your Tasks tables and have that be a foreign key to the Company table. Then you can set up a navigation property in the Company model:
public virtual ICollection<TaskType1> TasksType1 { get; set; }
You use an ICollection here because a company can have multiple tasks...if each company could only have one task, you could do something like:
public virtual TaskType1 TaskType1 { get; set; }
This lets you access the tasks like so:
companies = db.Companies.Include(i => i.TasksType1);
Have you checked out the Contoso University tutorial? It has a good introduction to establishing hierchical models and the associated relationships.
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application
(This is the MVC version, there is also a WebForms version of the tutorial if you are so inclined)

Define association using database column and not entity type property

public class Order {
public int OrderID {get; set;}
public DateTime DateOrdered { get; set; }
public ICollection<OrderLine> OrderLines { get; set; }
}
public class OrderLine{
public int OrderLineID { get; set; }
public int OrderID {get; set; } // I want to remove this
public string ItemName { get; set;}
public Int Qty { get; set; }
}
How would I map these using the Fluent API? I am using these in a repository pattern where Order will be the root of the aggregate. As such I do not want OrderLine to have a reference to Order or have an OrderID. Since the OrderLine only makes any sense because its a child of Order.
Currently I am using this:
HasMany<OrderLine>(x => x.OrderLines).WithRequired().HasForeignKey(x => x.OrderID);
I am using an existing database structure here and ideally I would map this using the database column name. So somehow tell it to use tblOrderLine.colOrderId rather then OrderLine.OrderID.
You can use the Map() method to map your FK
HasMany<OrderLine>(x => x.OrderLines)
.WithRequired()
.Map(m => m.MapKey("colOrderId"));

Resources