簡體   English   中英

在實體框架中建模嵌套數據結構

[英]Modeling nested data structures in Entity Framework

我正在嘗試Entity Framework 7 RC1(每個主要版本,我都會檢查一下是否值得解決),但是在嘗試理解如何建模某些實體時遇到了一些麻煩。

作為示例,我回到了一個簡單的真實應用程序中。 它用於管理Windows打印服務器(ugh)。

這是一些數據庫表的示例:

  • PrinterType :描述不同類型打印機(打印機,繪圖儀和MFP)的表
  • PrinterManufacturer :描述不同制造商(施樂,佳能,三星,惠普等)的表格
  • PrintServer :一個表,其中包含我們的打印服務器的名稱和描述
  • PrintServerSupport :映射服務器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方面的EF經驗非常有限)

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

但是,在調試時,這將返回以下相當奇怪的結果集:

結果視圖

如您所見,“制造商”和“類型”字段未填充。 奇怪的是,嵌套的服務器字段是...

為了使事情更加煩人,我還收到了帶有嵌套數據的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應該如何在這里提供幫助感到好奇。

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

我不認為在將導航屬性標記為virtual (例如在EF6中)默認情況下在EF 7中啟用了延遲加載。 這是為了減少不必要的數據庫旅行。

您可以使用ThenInclude加載相關實體

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

暫無
暫無

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

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