¿Puedo proyectar una referencia opcional de una entidad en una referencia opcional del tipo de resultado de la proyección?

Digamos, tengo dos entidades:

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 es unOpcional referencia (nula) enOrder (tal vez el sistema soporta pedidos "anónimos").

Ahora, quiero proyectar algunas propiedades de un pedido en un modelo de vista que incluye algunas propiedades del clienteSi El pedido tiene un cliente. Tengo dos clases de modelos de vista entonces:

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; }
}

Si elCustomer seria unnecesario propiedad de navegación enOrder Podría usar la siguiente proyección y funciona porque puedo estar seguro de que unaCustomer siempre existe para cualquierOrder:

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();

Pero esto no funciona cuandoCustomer Es opcional y el pedido con identificación.someOrderId No tiene un cliente:

EF se queja de que el valor materializado parao.Customer.SalesLevel esNULL y no puede ser almacenado en elintno propiedad nulableCustomerViewModel.SalesLevel. Eso no es sorprendente y el problema podría resolverse haciendoCustomerViewModel.SalesLevel de tipoint? (o en generaltodos propiedades anulables

Pero en realidad preferiría eso.OrderViewModel.CustomerViewModel se materializa comonull Cuando el pedido no tiene cliente.

Para lograr esto intenté lo siguiente:

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();

Pero esto arroja la infame excepción de LINQ to Entities:

No se puede crear un valor constante de tipo 'CustomerViewModel'. En este contexto solo se admiten los tipos primitivos (por ejemplo, '' Int32 ',' String 'und' Guid '').

Supongo: null es el "valor constante" paraCustomerViewModel lo cual no está permitido.

Desde la asignaciónnull No parece estar permitido. Intenté introducir una propiedad de marcador enCustomerViewModel:

public class CustomerViewModel
{
    public bool IsNull { get; set; }
    //...
}

Y luego la proyección:

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();

Esto tampoco funciona y lanza la excepción:

El tipo 'CustomerViewModel' aparece en dos inicializaciones incompatibles estructuralmente dentro de una sola consulta LINQ to Entities. Un tipo se puede inicializar en dos lugares en la misma consulta, pero solo si las mismas propiedades se configuran en ambos lugares y esas propiedades se configuran en el mismo orden.

La excepción es suficientemente clara cómo solucionar el problema:

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();

Esto funciona, pero no es una solución muy agradable para llenar todas las propiedades con valores ficticios onull explícitamente.

Preguntas:

¿Es el último fragmento de código la única solución, aparte de hacer que todas las propiedades de laCustomerViewModel nullable?

¿Es simplemente imposible materializar una referencia opcional anull en una proyección?

¿Tienes una idea alternativa de cómo lidiar con esta situación?

(Solo estoy poniendo el generalmarco de la entidad etiqueta para esta pregunta porque creo que este comportamiento no es específico de la versión, pero no estoy seguro. He probado los fragmentos de código anteriores con EF 4.2 /DbContext/ Código-Primero. Editar: Dos etiquetas más añadidas.)

Respuestas a la pregunta(1)

Su respuesta a la pregunta