![](/img/trans.png)
[英]EF Core self referencing not working if there are 2 foreign keys to self (Code first)
[英]Using EF Core Code First with no foreign keys
我正在嘗試使用代碼優先方法使用EF Core 2.1設計應用程序,但是我不希望在數據庫中使用外鍵。 我發現使用FK確實很痛苦,尤其是在嘗試運行dotnet ef database drop
。 運行此命令時出錯,因為我的數據庫中有外鍵。
我只想不必擔心外鍵,而只需將具有Id
屬性的表用於相關項目即可。 如果/當我需要相關信息時,我將從數據庫中獲取相關項目。
public class Employer : BaseEntity
{
public string Name { get; set; }
public string Description { get; set; }
public ICollection<Employee> Employees { get; set; }
public ICollection<Client> Clients { get; set; }
}
public class Employee : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public EmployeeType EmployeeType { get; set; }
public Guid EmployerId { get; set; }
public Employer Employer { get; set; }
}
public class Client : BaseEntity
{
public string Name { get; set; }
public int EmployerId { get; set; }
public Employer Employer { get; set; }
}
使用關系數據庫時,數據庫中的每個對象都需要一個ID,如果該對象“屬於”另一個表中的另一個對象,則需要一個外鍵。 你不能沒有它。
幸運的是,實體框架足夠聰明,因此,如果設計合理,就很少使用外鍵執行(組)聯接。 您通常使用虛擬屬性。
在實體框架中,這些類表示數據庫的表。 表中的列由類的非虛擬屬性表示。 虛擬屬性表示類之間的關系。
因此,您具有一些BaseEntity
和三種特殊類型的BaseEntities
: Employers
, Employees
和Clients
。
每個Employer
都有零個或多個Employees
; 每個Employee
只有一個Employer
:一個簡單的一對多關系。 為此,無論您是否喜歡,每個Employee
需要一個屬於其Employer
的外鍵。 幸運的是,您不必使用它。
同樣, Employer
與Client
之間存在一對多的關系:每個Employer
零個或多個Clients
,每個Client
使用外鍵恰好屬於一個Employer
。
使用實體框架代碼優先約定,您的類將需要稍作更改:表之間的關系應標記為虛擬。
class Employer : BaseEntity
{
public int Id {get; set;}
// every Employer has zero or more Employees:
public virtual ICollection<Employee> Employees { get; set; }
// every Employer has zero or more Clients:
public virtual ICollection<Client> Clients { get; set; }
...
}
class Employee : BaseEntity
{
public int Id {get; set;}
// every Employee belongs to exactly one Employer, using a foreign key:
public int EmployerId {get; set;}
public virtual Employer Employer { get; set; }
...
}
class Client : BaseEntity
{
public int Id {get; set;}
// Every Client belongs to exactly one Employer, using foreign key:
public int EmployerId { get; set; }
public virtual Employer Employer { get; set; }
...
}
重要的變化是表之間的關系被標記為虛擬
注意:可能是您不希望整數用作主鍵。 那不會改變想法。
要執行(分組)聯接表的查詢,您無需使用外鍵,
給我所有(或一些)雇主以及所有(或一些)他的客戶和雇員。
為此,您將使用GroupJoin:每個獲取的雇主都將有一個“客戶和雇員”子集合。 使用實體框架,您不必自己加入:
var result = dbContext.Employers // From every employer in the sequence ofall Employers
.Where(employer => ...) // or only some of them
.Select(employer => new // make one new object
{
// select only the properties you actually plan to use
Id = employer.Id,
Name = employer.Name,
Employees = employer.Employees
.Where(employee => ...) // only if you do not want all Employees
.Select(employee => new
{
// again, select only the properties you plan to use
Id = employee.Id,
Name = employee.Name,
...
})
.ToList(),
Clients = employer.Clients
.Where(client=> ...) // only if you do not want all Clients
.Select(client => new
{
...
})
.ToList(),
});
實體框架知道您設計了一對多,並會為您做適當的連接。 盡管您沒有提到任何外鍵,但是實體框架知道所涉及的外鍵。
請注意,通過這種方式,您還將獲得沒有客戶或雇員的雇主
如果您不希望“帶有其子對象的對象”(GroupJoin),而又希望獲得平坦的結果(更像是Join),請從子對象開始:
給我所有(或一些)客戶及其雇主
var result = dbContext.Clients.Select(client => new
{
Id = client.Id,
Name = client.Name,
...
Employer = new
{
Id = client.Employer.Id,
...
},
});
實體框架知道您設計了一對多,並會為您做適當的連接。
請注意,沒有客戶,您將無法獲得雇主。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.