2016-03-07 42 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”。 –