2016-03-07 158 views
0

我嘗試了實體框架7 RC1(每個主要版本,我檢查是否值得麻煩),但我有一些麻煩,試圖瞭解我如何應該模擬某些實體。實體框架中的嵌套數據結構建模

作爲一個例子,我回到了一個簡單的現實世界的應用程序。它是用來管理Windows打印服務器(唉)。

下面是一些數據庫表的一個示例:

  • PrinterType:甲表描述不同類型的打印機 (打印機,繪圖儀和MFP)的
  • PrinterManufacturer:一個表描述 不同廠商(施樂,佳能,三星,惠普等)
  • 打印服務器:和我們的打印說明 服務器
  • 打印服務器支持:映射服務器ID,類型ID和製造商ID以顯示打印服務器支持哪些特定打印機的表。

這裏的DDL:

CREATE TABLE dbo.PrintServer 
(
    ID   INT IDENTITY NOT NULL, 
    Name  VARCHAR(MAX) NOT NULL, 
    Description VARCHAR(MAX) NULL, 
    CONSTRAINT [PK_PrintServer_ID] PRIMARY KEY (ID), 
) 

CREATE TABLE dbo.PrintServerSupport 
(
    ID    INT IDENTITY NOT NULL, 
    ServerID  INT NOT NULL, 
    TypeID   INT NOT NULL, 
    ManufacturerID INT NOT NULL, 
    CONSTRAINT [PK_PrintServerSupport_ID] PRIMARY KEY (ID), 
    CONSTRAINT [FK_PrintServerSupport_ServerID] FOREIGN KEY (ServerID) REFERENCES PrintServer (ID) ON DELETE CASCADE, 
    CONSTRAINT [FK_PrintServerSupport_TypeID] FOREIGN KEY (TypeID) REFERENCES PrinterType (ID) ON DELETE CASCADE, 
    CONSTRAINT [FK_PrintServerSupport_ManufacturerID] FOREIGN KEY (ManufacturerID) REFERENCES PrinterManufacturer (ID) ON DELETE CASCADE 
) 

CREATE TABLE dbo.PrinterType 
(
    ID   INT IDENTITY NOT NULL, 
    Type  VARCHAR(MAX) NOT NULL, 
    CONSTRAINT [PK_PrinterType_ID] PRIMARY KEY (ID), 
) 

CREATE TABLE dbo.PrinterManufacturer 
(
    ID    INT IDENTITY NOT NULL, 
    Manufacturer VARCHAR(MAX) NOT NULL, 
    CONSTRAINT [PK_PrinterManufacturer_ID] PRIMARY KEY (ID) 
) 

現在,把這個放到C#POCO實體將明顯地達到這些方針的東西:

public partial class PrinterManufacturer 
{ 
    public PrinterManufacturer() 
    { 
     PrintServerSupport = new HashSet<PrintServerSupport>(); 
    } 

    public int ID { get; set; } 
    public string Manufacturer { get; set; } 

    public virtual ICollection<PrintServerSupport> PrintServerSupport { get; set; } 
} 

public partial class PrinterType 
{ 
    public PrinterType() 
    { 
     PrintServerSupport = new HashSet<PrintServerSupport>(); 
    } 

    public int ID { get; set; } 
    public string Type { get; set; } 

    public virtual ICollection<PrintServerSupport> PrintServerSupport { get; set; } 
} 

public partial class PrintServer 
{ 
    public PrintServer() 
    { 
     PrintServerSupport = new HashSet<PrintServerSupport>(); 
    } 

    public int ID { get; set; } 
    public string Description { get; set; } 
    public string Name { get; set; } 

    public virtual ICollection<PrintServerSupport> PrintServerSupport { get; set; } 
} 

public partial class PrintServerSupport 
{ 
    public int ID { get; set; } 
    public int ManufacturerID { get; set; } 
    public int ServerID { get; set; } 
    public int TypeID { get; set; } 

    public virtual PrinterManufacturer Manufacturer { get; set; } 
    public virtual PrintServer Server { get; set; } 
    public virtual PrinterType Type { get; set; } 
} 

現在,像我想選擇所有打印服務器,我只需要執行以下操作? (請記住我的EF英孚的經驗是非常有限的)

using (var db = new DbContext()) 
{ 
    var query = db.PrintServer.Include(s => s.PrintServerSupport); 
} 

然而,在調試的時候,這將返回以下比較奇怪的結果集:

Result view

正如你所看到的,製造商和類型字段不填充。奇怪的是,嵌套的服務器字段...

爲了使事情更煩人,我也接收JSON有效載荷與嵌套數據。這裏有一個例子:

[ 
    { 
     "Name":"REDACTED", 
     "Description":"Xerox MFP TEST", 
     "SupportedPrinters": [ 
      { 
       "Type":"Printer", 
       "Manufacturer":"XEROX" 
      }, 
      { 
       "Type":"Plotter", 
       "Manufacturer":"XEROX" 
      }, 
      { 
       "Type":"MFP", 
       "Manufacturer":"XEROX" 
      } 
     ] 
    }, 
    { 
     "Name":"REDACTED-2", 
     "Description":"Xerox MFP TEST 2", 
     "SupportedPrinters": [ 
      { 
       "Type":"Printer", 
       "Manufacturer":"SAMSUNG" 
      }, 
      { 
       "Type":"Plotter", 
       "Manufacturer":"SAMSUNG" 
      } 
     ] 
    } 
] 

編組和解組這個數據是小菜一碟,但對於和解組數據,然後更新數據庫?我總是覺得這是一個相當困難的問題,我很好奇EF如何幫助這裏。

建模和查詢數據的正確方法是什麼?

回答

1

當您標記導航屬性virtual(如EF6中)時,我不認爲在EF 7中默認啓用延遲加載。這是爲了減少不必要的訪問數據庫。

您可以通過使用ThenInclude

using (var db = new DbContext()) 
{ 
    var query = db.PrintServer.Include(s => s.PrintServerSupport) 
          .ThenInclude(p => p.Manufacturer); 
} 
+0

感謝加載相關實體,可以讓我加載導航性能中的至少一個。有沒有一種方法可以包含Type導航屬性?看來我只能「跟隨」其中一個屬性(我不能鏈接ThenIncludes) –

+0

沒關係,好​​像我需要在這種情況下指定兩次「Include」。 –