簡體   English   中英

一對多關系不檢索實體框架中的數據

[英]One to many relationship doesn`t retrieve data in entity framework

我正在學習 C# & .NET 和 EF(使用aspnetboilerplate ),我想出了創建一些虛擬項目的想法,以便我可以練習。 但是最后 4 小時我堅持這個錯誤,希望這里有人可以幫助我。

我創建的(至少我認為我正確地創建了它)是 2 個名為“成分”和“大師”的類

我想用它對“大師”類的成分進行分類。

例如成分像

  • 雞胸肉
  • 雞腿

它們都屬於 Meat(女巫在“Master”數據庫中輸入),這是我的代碼

成分.cs

   public class Ingrident : Entity
{

    public string Name { get; set; }
    public Master Master { get; set; }
    public int MasterId { get; set; }

}

碩士.cs

public class Master : Entity

    {
        public string Name { get; set; }
        public List<Ingrident> Ingridents { get; set; } = new();
    
    }

IngridientAppService.cs

public List<IngridientDto> GetIngWithParent()
    {
        var result = _ingRepository.GetAllIncluding(x => x.Master);
         //Also I try this but doesn`t work 
        // var result = _ingRepository.GetAll().Where(x => x.MasterId == x.Master.Id);
        return ObjectMapper.Map<List<IngridientDto>>(result);
    }

配料表

  [AutoMap(typeof(IndexIngrident.Entities.Ingrident))]

public class IngridientDto : EntityDto
{
    public string Name { get; set; }
    public List<MasterDto> Master { get; set; }

    public int MasterId { get; set; }
 }

MasterDto.cs

    [AutoMap(typeof(IndexIngrident.Entities.Master))]

    public class MasterDto : EntityDto
    {
     public string Name { get; set; }
    }

當我創建(最后一次練習)M -> M 關系時,這種方法與 .getAllIn包括工作,但現在當我有一個 -> 許多時,它就行不通了。

希望有人能夠幫助我或至少給我一些好的提示。

祝你今天過得愉快 !

直接說明您可能引用的示例(關於存儲庫等)過於復雜,並且在大多數情況下,不是您想要實現的。

我看到的第一個問題是,雖然您的實體設置為從主到成分的一對多關系,但您的 DTO 是從成分到主設置的,這肯定不會正確映射。

從最簡單的事情開始。 擺脫存儲庫並擺脫 DTO。 我不確定基類“Entity”的作用,但我猜它公開了一個名為“Id”的通用鍵屬性。 對於初學者,我可能也會放棄。 當涉及到主鍵時,通常有兩種命名方法,每個表都使用一個名為“Id”的 PK,或者每個表使用一個表名后綴為“Id”的 PK。 即“Id”與“IngredientId”。 我個人認為第二個選項在配對 FK 和 PK 時非常清楚,因為它們具有相同的名稱。

當談到通過導航屬性表示關系時,一個重要的細節是確保導航屬性鏈接到它們各自的 FK 屬性(如果存在),或者更好的是,為 FK 使用陰影屬性。

例如,對於您的 Ingredient 表,擺脫 Entity 基類:

[Table("Ingredients")]
public class Ingredient : Entity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int IngredientId { get; set; }
    public string Name { get; set; }
    public int MasterId { get; set; }
    [ForeignKey("MasterId")]
    public virtual Master Master { get; set; }
}

此示例使用 EF 屬性來幫助告訴 EF 如何將實體屬性解析為相應的表和列,以及 Ingredient 和 Master 之間的關系。 EF 可以通過約定來解決大部分問題,但最好理解並明確應用它,因為最終您會遇到約定無法按預期工作的情況。

識別(主)鍵並指出它是一個身份列也告訴 EF 期望數據庫將自動填充 PK。 (強烈推薦)

在 Master 端,我們做類似的事情:

[Table("Masters")]
public class Master : Entity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int MasterId { get; set; }
    public string Name { get; set; }
    [InverseProperty("Master")]
    public virtual ICollection<Ingredient> Ingredients { get; set; } = new List<Ingredient>();
}

我們再次表示主鍵,對於我們的成分集合,我們告訴 EF 在另一側(成分)應該使用什么屬性來關聯到使用InverseProperty屬性的 Master 的成分列表。

屬性只是設置關系等的一個選項。其他選項是使用實現IEntityConfiguration<TEntity> (EF Core) 的配置類,或將它們配置為OnModelCreating事件的一部分。 最后一個選項我只推薦用於非常小的項目,因為它可以很快開始成為一種上帝的方法。 您可以將其拆分為對各種私有方法的調用,但您也可以只使用IEntityConfiguration類。

現在,當您使用 Master 或 Master 獲取其成分時:

using (var context = new AppDbContext())
{
    var ingredients = context.Ingredients
        .Include(x => x.Master)
        .Where(x => x.Master.Name.Contains("chicken"))
        .ToList();
    // or

    var masters = context.Master
        .Include(x => x.Ingredients)
        .Where(x => x.Name.Contains("chicken"))
        .ToList();

   // ...
}

存儲庫模式是一個更高級的概念,有幾個很好的理由來實現,但在大多數情況下,它們不是必需的,並且是 EF 實現中的反模式。 我認為通用存儲庫始終是 EF 實現的反模式。 Repository<Ingredient>使用存儲庫,尤其是 EF 的通用存儲庫的主要原因是您會自動增加實現的復雜性和/或削弱 EF 可以為您的解決方案帶來的功能。 正如您在使用示例時看到的那樣,簡單地將急切加載傳遞到存儲庫意味着編寫復雜的Expression<Func<TEntity>>參數,而這僅涵蓋了急切加載。 如果沒有 EF 開箱即用的這些功能,支持投影、分頁、排序等會增加更多樣板復雜性或限制您的解決方案和性能。

考慮研究存儲庫實現 /w EF 的一些充分理由:

  • 促進單元測試。 (存儲庫比 DbContexts/DbSets 更容易模擬)
  • 集中低級數據規則,例如租賃、軟刪除和授權。

考慮存儲庫的一些不好(盡管很常見)的原因:

  • 從對 EF 的依賴關系的引用或知識中提取代碼。
  • 抽象代碼,以便可以替換 EF。

投影到 DTO 或 ViewModel 是使用 EF 構建高效且安全的解決方案的一個重要方面。 目前尚不清楚“ObjectMapper”是什么,無論它是 Automapper Mapper 實例還是其他東西。 我強烈建議通過使用 Linq 的Select語法從模型中填充所需的 DTO 來開始掌握投影。 使用投影時,正確的第一個關鍵的區別是,當你的項目的對象圖,你不必急於左右裝載相關實體的擔心。 投影 ( Select ) 中引用的任何相關實體/屬性將根據需要自動加載。 稍后,如果您想利用 Automapper 之類的工具來幫助消除Select語句的混亂,您將需要配置映射配置,然后使用 Automapper 的ProjectTo方法而不是Map ProjectTo與 EF 的IQueryable實現一起使用,將您的映射解析為 SQL,就像Select一樣,其中Map需要返回所有預先加載的內容以填充相關數據。 ProjectToSelect可以產生更高效的查詢,與 Eager Loading 整個對象圖相比,可以更好地利用索引。 (數據庫和服務器/應用程序之間的線路上的數據較少) Map仍然非常有用,例如您希望將值從 DTO 復制回已加載實體的場景。

像這樣做

public class Ingrident:Entity
{

    public string Name { get; set; }
    [ForeignKey(nameof(MasterId))]
    public Master Master { get; set; }
    public int MasterId { get; set; }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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