Reputation: 1477
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.
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).
Here's an example of some of the database tables:
Here's the 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:
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)
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. 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.
What is the correct way of both modeling the data and querying it?
Upvotes: 0
Views: 211
Reputation: 3612
I don't think lazy loading is enabled by default in EF 7 when you mark your navigation properties virtual
(like in EF6). This is to reduce unnecessary trips to the database.
You can load your related entities by using ThenInclude
using (var db = new DbContext())
{
var query = db.PrintServer.Include(s => s.PrintServerSupport)
.ThenInclude(p => p.Manufacturer);
}
Upvotes: 1