简体   繁体   English

在实体框架中建模嵌套数据结构

[英]Modeling nested data structures in Entity Framework

I'm trying out Entity Framework 7 RC1 (every major version, I check back to see if it's worth the hassle), but I'm having some trouble trying to understand how I'm supposed to model certain entities. 我正在尝试Entity Framework 7 RC1(每个主要版本,我都会检查一下是否值得解决),但是在尝试理解如何建模某些实体时遇到了一些麻烦。

As an example I went back to a simple real-world application I have lying around. 作为示例,我回到了一个简单的真实应用程序中。 It was made to manage Windows print servers (ugh). 它用于管理Windows打印服务器(ugh)。

Here's an example of some of the database tables: 这是一些数据库表的示例:

  • PrinterType : A table describing the different types of printers (Printers, plotters and MFPs) PrinterType :描述不同类型打印机(打印机,绘图仪和MFP)的表
  • PrinterManufacturer : A table describing different manufacturers (Xerox, Canon, Samsung, HP, etc.) PrinterManufacturer :描述不同制造商(施乐,佳能,三星,惠普等)的表格
  • PrintServer : A table holding name and description of our print servers PrintServer :一个表,其中包含我们的打印服务器的名称和描述
  • PrintServerSupport : A table mapping the Server ID, Type ID and Manufacturer ID to show which specific printers a print server supports. PrintServerSupport :映射服务器ID,类型ID和制造商ID的表,以显示打印服务器支持哪些特定打印机。

Here's the DDL: 这是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)
)

Now, turning this into C# POCO entities would apparently amount to something along these lines: 现在,将其转换为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; }
}

Now, image I would want to select all print servers, I would merely have to do the following? 现在,图像我想选择所有打印服务器,我只需要执行以下操作? (Please keep in mind my EF experience with EF is very limited) (请记住,我在EF方面的EF经验非常有限)

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

However, when debugging, this returns the following rather strange resultset: 但是,在调试时,这将返回以下相当奇怪的结果集:

结果视图

As you can see, the Manufacturer and Type fields are not populated. 如您所见,“制造商”和“类型”字段未填充。 Curiously enough, the nested Server fields are... 奇怪的是,嵌套的服务器字段是...

To make things even more annoying, I'm also receiving JSON payloads with nested data. 为了使事情更加烦人,我还收到了带有嵌套数据的JSON有效负载。 Here's an example: 这是一个例子:

[
    {
        "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"
            }
        ]
    }
]

Marshaling and unmarshaling this data is a piece of cake, but what about unmarshaling data, and then updating the database? 对数据进行封送和拆封是一件容易的事,但是对数据进行封送再更新数据库又如何呢? I always found it to be pretty difficult problem, and I'm curious as to how EF is supposed to help out here. 我总是发现这是一个非常困难的问题,并且我对EF应该如何在这里提供帮助感到好奇。

What is the correct way of both modeling the data and querying it? 数据建模和查询的正确方法是什么?

I don't think lazy loading is enabled by default in EF 7 when you mark your navigation properties virtual (like in EF6). 我不认为在将导航属性标记为virtual (例如在EF6中)默认情况下在EF 7中启用了延迟加载。 This is to reduce unnecessary trips to the database. 这是为了减少不必要的数据库旅行。

You can load your related entities by using ThenInclude 您可以使用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