Tengo una subconsulta devuelve el valor más reciente de una tabla secundaria. En algunos casos la subconsulta no devuelve nada. La consulta siguiente genera un error en tiempo de ejecución, porque el tipo inferido de MemberPrice es decimal y no acepta valores null.

Simplificado de consulta:

Dim q = From s In dc.STOCKs _
        Select s.ID, MemberPrice = _
          (From mp In dc.STOCKPRICEs Where mp.NUMBER = s.NUMBER _
          Order By dc.date Descending _
          Select mp.PRICE).FirstOrDefault

En SQL, la subconsulta se incluiría en la parte Superior (1) y devolvería Null cuando está vacío. ¿Cómo puedo manejar esto en LINQ? Es allí una manera de hacer MemberPrice que aceptan valores null o por defecto el valor de cero si no se encuentra (o una solución más elegante)?

Muchas gracias, Stuart

  • Se puede definir lo que significa no? FirstOrDefault debe devolver Nada si la subconsulta está vacía y, por tanto, la MemberPrice debe ser 0 en ese caso.
  • Tengo un Sistema.InvalidOperationException {«El valor nulo no puede ser asignado a un miembro con el tipo de Sistema.Decimal que es un no aceptan tipo de valor.»}. Yo también estaba esperando para devolver 0 si es null, así que me debe faltar algo.
  • ¿Cuál es el tipo de mp.PRECIO?
  • Es de tipo Decimal.
  • Te encontraste la solución? Porque tengo el mismo problema.
  • Sí Roberts respuesta a continuación es la solución. La conversión a un tipo que acepta valores null resuelve toda una clase de problemas que yo he tenido.
  • Para mayor aclaración, el FirstOrDefault es el resultado de convertir a partir de una secuencia de Decimal a una sola Decimal?. Que es la fuente de la nulos.

InformationsquelleAutor Stuart | 2009-05-24

4 Comentarios

  1. 6

    Stuart,

    He cambiado mi campo de Precio en la base de datos no permite valores nulos, y tengo el mismo error que hizo:

    "Operator '??' cannot be applied to operands of type 'decimal' and 'int'". 

    Como usted ha señalado, cuando el Precio está ajustado para no permitir valores null en la base de datos, la nula creación de operador ya no funciona porque se está a la espera para ver a un tipo que acepta valores null decimal:

    decimal?

    Si puedo quitar la nula creación de operador y ejecutar el caso de prueba que no contenga un precio, me sale:

    "The null value cannot be assigned to a member with type System.Decimal which is a non-nullable value type.."

    Aquí está el código que funciona. Yo echo la subconsulta resultado a decimal? antes de aplicar la nula creación de operador.

    public class Class1
    {
    
        DataClasses1DataContext dc = new DataClasses1DataContext();
    
        public decimal test(int stockID)
        {
    
            var q = from s in dc.Stocks
                    where s.StockID == stockID
                    select new
                    {
                        StockID = s.StockID,
                        memberPrice = ((decimal?)(from mp in dc.StockPrices
                                       where mp.StockID == s.StockID
                                       select mp.Price).FirstOrDefault()) ?? 0
                    };
    
            return q.FirstOrDefault().memberPrice;
        }
    }
    • Robert, muchas gracias por pasar por encima y más allá para resolver este problema.
  2. 3

    Stuart, intente esto:

    Dim q = From s In dc.STOCKs _
        Select s.ID, MemberPrice = _
          if((From mp In dc.STOCKPRICEs Where mp.NUMBER = s.NUMBER _
          Order By dc.date Descending _
          Select mp.PRICE).FirstOrDefault),0)

    La nula creación de operador, presionará el valor null a cero para MemberPrice.

    • La nula creación de operador ?? no existe en vb.net
    • Sí, así es: La función Si. Como en el Caso de que(possibleNullValue, valueIfNull)
    • He editado el ejemplo de código para usar VB.Net’s versión de la creación de operador.
    • Me sale el siguiente error del compilador: «Primer operando en un sistema binario ‘Si’ expresión debe ser que aceptan valores null o un tipo de referencia.»
    • Ok, vamos a intentar combinar el resultado completo (nuevo código de arriba).
    • Estoy recibiendo el mismo error del compilador, ya MemberPrice se infiere a ser un tipo de valor (decimal).

  3. 0

    Hace el defaultifempty junto método de extensión de hacer lo que estás buscando?

    • Lo he utilizado para tv de combinaciones externas, pero no podía encontrar la manera de conseguir alrededor de la asignación de nada para el mp.Precio valor decimal tipo. ¿Tiene usted alguna idea sobre la sintaxis yo podría tratar?
  4. 0

    Stuart,

    Esta es la forma en que yo tengo que trabajar en mi máquina. Me disculpo por no estar en c#; ha sido mucho tiempo desde que he usado VB.

    Nota el uso del operador «new» en la opción «seleccionar» de la declaración, y el uso de la nula creación de operador después de que el FirstOrDefault().

    public class Class1
    {
    
        DataClasses1DataContext dc = new DataClasses1DataContext();
    
        public decimal MemberPrice(int stockID)
        {
    
            var q = from s in dc.Stocks
                    where s.StockID == stockID
                    select new
                    {
                        StockID = s.StockID,
                        memberPrice = (from mp in dc.StockPrices
                                       where mp.StockID == s.StockID
                                       select mp.Price).FirstOrDefault() ?? 0
                    };
    
            return q.FirstOrDefault().memberPrice;
        }
    }
    • Estoy recibiendo el mismo error de compilador con este código en C# porque memberPrice se infiere como un decimal (vs acepta valores null<decimal>). El error es «Operador»??’ no se puede aplicar a los operandos de tipo ‘decimal’ y ‘int'». ¿Cuál es el tipo de Precio en su máquina?
    • El tipo de Precio que en mi máquina es Decimal(18,0) Permitir valores Nulos.

Dejar respuesta

Please enter your comment!
Please enter your name here