2010-11-29 22 views
8

Tengo una tabla de base de datos que contiene una columna nvarchar así:String.Split en una consulta Linq-To SQL?

1|12.6|18|19 

que tienen un objeto de negocio que tiene un decimal [] propiedad.

Mi consulta LINQ se ve así:

var temp = from r in db.SomeTable select new BusinessObject { 
    // Other BusinessObject Properties snipped as they are straight 1:1 
    MeterValues = r.MeterValues.Split('|').Select(Decimal.Parse).ToArray() 
}; 
var result = temp.ToArray(); 

Esto arroja una NotSupportedException: Method 'System.String[] Split(Char[])' has no supported translation to SQL.

que aspira un poco :) ¿Hay alguna manera de hacer esto sin tener que añadir una propiedad de cadena a la objeto comercial o seleccionando un tipo anónimo y luego iterando a través de él?

Mi "solución" actual es:

var temp = from r in db.SomeTable select new { 
    mv = r.MeterValues, 
    bo = new BusinessObject { // all the other fields } 
}; 
var result = new List<BusinessObject>(); 
foreach(var t in temp) { 
    var bo = t.bo; 
    bo.MeterValues = t.mv.Split('|').Select(Decimal.Parse).ToArray(); 
    result.Add(bo); 
} 
return result.ToArray(); // The Method returns BusinessObject[] 

Eso es un poco fea, sin embargo, con esa lista temporal.

He intentado añadir un let mv = r.MeterValues.Split('|').Select(Decimal.Parse).ToArray() pero que conduce esencialmente a la misma NotSupportedException.

Ésta es 3.5SP1 .net si lo que importa.

Respuesta

6

necesita forzar la cláusula select a ejecutar en el cliente llamando .AsEnumerable() primera:

var result = db.SomeTable.AsEnumerable().Select(r => new BusinessObject { 
    ... 
    MeterValues = r.MeterValues.Split('|').Select(Decimal.Parse).ToArray() 
}).ToList(); 
+1

¿Eso seleccionar toda la tabla alguna_tabla sin embargo? –

+0

@Michael: Sí. Debe seleccionar la tabla completa de todos modos. Si solo necesita un subconjunto de los campos, puede poner un 'Seleccionar' inicial antes del' .AsEnumerable'. – SLaks

+2

Sí, esto no es ideal, básicamente ejecutará un "SELECT * FROM SomeTable". ¿L2SQL es compatible con UDF? EF lo hace (creo). Si es así, usted podría hacer que el lado del servidor de división (por ejemplo UDF) – RPM1984

1

Desafortunadamente su IQueryable la que está utilizando (LINQ to SQL) que no está apoyando la función Split.

Usted está en realidad sólo se queda con el IEnumerable (LINQ a Objetos) apoyo a la misma en este caso. Usted segundo fragmento de código es lo que hay que hacer, o algo así ...

var temp = (from r in db.SomeTable select new { 
    mv = r.MeterValues, 
    bo = new BusinessObject { // all the other fields } 
}).AsEnumerable().Select(blah, blah) ; 
2

No es necesario utilizar una lista temporal:

var query = from r in db.SomeTable 
      select new 
      { 
       r.Id, 
       r.Name, 
       r.MeterValues, 
       ... 
      }; 

var temp = from x in query.AsEnumerable() 
      select new BusinessObject 
      { 
       Id = x.Id, 
       Name = x.Name, 
       MeterValues = x.mv.Split('|').Select(Decimal.Parse).ToArray(), 
       ... 
      }; 

return temp.ToArray(); 
2

No se puede usar la división, pero en este escenario, puede hacer lo siguiente:

// Database value is 1|12.6|18|19 

string valueToFind = "19"; 

var temp = from r in db.SomeTable.Where(r => ("|" + r.MeterValues + "|").Contains("|" + valueToFind + "|")); 

este código añade tubos exteriores (|) para el valor de la base de datos sobre la marcha dentro de la consulta, por lo que puede hacer empezar, el medio y el valor final de los partidos en la cadena.

Por ejemplo, el código anterior busca "| 19 |" dentro de "| 1 | 12.6 | 18 | 19 |", que se encuentra y es válido. Esto funcionará para cualquier otro valueToFind.