簡體   English   中英

無外鍵使用EF Core 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和三種特殊類型的BaseEntitiesEmployersEmployeesClients

每個Employer都有零個或多個Employees ; 每個Employee只有一個Employer :一個簡單的一對多關系。 為此,無論您是否喜歡,每個Employee需要一個屬於其Employer的外鍵。 幸運的是,您不必使用它。

同樣, EmployerClient之間存在一對多的關系:每個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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM