Sprich, ich habe zwei Entitäten:Kann ich eine optionale Referenz einer Entität in eine optionale Referenz des Ergebnistyps der Projektion projizieren?
public class Customer
{
public int Id { get; set; }
public int SalesLevel { get; set; }
public string Name { get; set; }
public string City { get; set; }
}
public class Order
{
public int Id { get; set; }
public DateTime DueDate { get; set; }
public string ShippingRemark { get; set; }
public int? CustomerId { get; set; }
public Customer Customer { get; set; }
}
Customer
ist eine optional (nullable) Referenz in Order
(möglicherweise unterstützt das System "anonymous" Aufträge).
Nun möchte ich einige Eigenschaften eines Auftrags in ein Ansichtsmodell einschließlich einiger Eigenschaften des Kunden projizieren, wenn der Auftrag einen Kunden hat. Ich habe zwei Ansicht Modellklassen dann:
public class CustomerViewModel
{
public int SalesLevel { get; set; }
public string Name { get; set; }
}
public class OrderViewModel
{
public string ShippingRemark { get; set; }
public CustomerViewModel CustomerViewModel { get; set; }
}
Wenn die Customer
eine erforderlich Navigationseigenschaft in Order
würde ich die folgende Projektion verwenden könnte und es funktioniert, weil ich sicher sein kann, dass ein Customer
existiert immer für jeden Order
:
OrderViewModel viewModel = context.Orders
.Where(o => o.Id == someOrderId)
.Select(o => new OrderViewModel
{
ShippingRemark = o.ShippingRemark,
CustomerViewModel = new CustomerViewModel
{
SalesLevel = o.Customer.SalesLevel,
Name = o.Customer.Name
}
})
.SingleOrDefault();
Aber das funktioniert nicht, wenn Customer
mit Id someOrderId
optional und die Reihenfolge ist noch kein Kunde:
EF wirft der materialisierten Wert für
o.Customer.SalesLevel
NULL
ist und nicht in derint
gespeichert werden können, nicht auf NULL festlegbare EigenschaftCustomerViewModel.SalesLevel
. Das ist nicht überraschend, und das Problem, indem sieCustomerViewModel.SalesLevel
vom Typ gelöst werden kannint?
(oder allgemein alle Eigenschaften nullable)Aber ich würde eigentlich lieber, wenn
OrderViewModel.CustomerViewModel
alsnull
materialisiert wird, wenn der Auftrag keine Kunden hat.
Um dies zu erreichen habe ich versucht, die folgenden:
OrderViewModel viewModel = context.Orders
.Where(o => o.Id == someOrderId)
.Select(o => new OrderViewModel
{
ShippingRemark = o.ShippingRemark,
CustomerViewModel = (o.Customer != null)
? new CustomerViewModel
{
SalesLevel = o.Customer.SalesLevel,
Name = o.Customer.Name
}
: null
})
.SingleOrDefault();
Aber die berüchtigte LINQ to Entities Ausnahme auslöst:
kann nicht einen konstanten Wert des Typs 'CustomerViewModel' erstellen. Nur primitive Typen (zum Beispiel '' Int32 ',' String 'und' Guid '') werden in diesem Zusammenhang unterstützt.
Ich denke, dass : null
ist der „konstante Wert“ für CustomerViewModel
was nicht erlaubt ist.
Da null
Zuordnung scheint nicht zu dürfen, habe ich versucht, einen Marker Eigenschaft in CustomerViewModel
vorstellen:
public class CustomerViewModel
{
public bool IsNull { get; set; }
//...
}
Und dann die Projektion:
OrderViewModel viewModel = context.Orders
.Where(o => o.Id == someOrderId)
.Select(o => new OrderViewModel
{
ShippingRemark = o.ShippingRemark,
CustomerViewModel = (o.Customer != null)
? new CustomerViewModel
{
IsNull = false,
SalesLevel = o.Customer.SalesLevel,
Name = o.Customer.Name
}
: new CustomerViewModel
{
IsNull = true
}
})
.SingleOrDefault();
Dies funktioniert auch nicht und wirft die Ausnahme:
Der Typ 'CustomerViewModel' erscheint in zwei str urbanisch inkompatible Initialisierungen innerhalb einer einzelnen LINQ to Entities-Abfrage. Ein Typ kann an zwei Stellen in der gleichen Abfrage initialisiert werden, aber nur wenn dieselben Eigenschaften an beiden Stellen festgelegt sind und diese Eigenschaften in der gleichen Reihenfolge in der festgelegt werden.
Die Ausnahme ist klar genug, wie das Problem zu beheben:
OrderViewModel viewModel = context.Orders
.Where(o => o.Id == someOrderId)
.Select(o => new OrderViewModel
{
ShippingRemark = o.ShippingRemark,
CustomerViewModel = (o.Customer != null)
? new CustomerViewModel
{
IsNull = false,
SalesLevel = o.Customer.SalesLevel,
Name = o.Customer.Name
}
: new CustomerViewModel
{
IsNull = true,
SalesLevel = 0, // Dummy value
Name = null
}
})
.SingleOrDefault();
Dies funktioniert, aber es ist nicht eine sehr schöne Abhilfe alle Eigenschaften mit Dummy-Werten oder null
explizit zu füllen.
Fragen:
ist der letzte Code-Schnipsel, die einzige Lösung, beiseite alle Eigenschaften des
CustomerViewModel
nullable aus machen?Ist es einfach nicht möglich, eine optionale Referenz auf
null
in einer Projektion zu materialisieren?Haben Sie eine alternative Idee, wie Sie mit dieser Situation umgehen können?
(Ich bin nur den allgemeinen Entity-Framework Tag für diese Frage einstellen, weil ich dieses Verhalten nicht erraten Version spezifisch ist, aber ich bin nicht sicher. Ich den Code-Schnipsel oben mit EF 4.2 getestet/DbContext
/Code-First. Bearbeiten: Zwei weitere Tags hinzugefügt.)
Haben Sie jemals eine Lösung dafür gefunden? und wenn ja, würden Sie gerne teilen :) –
@QuintonBernhardt: Nein, ich habe keine Lösung gefunden. Ich umgehe dies hauptsächlich, indem ich alle geschachtelten Ansichtsmodelleigenschaften auf Null setzen kann. – Slauma