2008-12-18 20 views
6

Tengo algunos problemas con el uso del método de extensión OrderBy en una consulta LINQ cuando está operando en un tipo de enumeración. He creado un DataContext normal usando Visual Studio simplemente arrastrando y soltando todo en el diseñador. Luego creé modelos de entidades separados, que son simplemente POCO, y utilicé un patrón de repositorio para obtener los datos de mi base de datos y asignarlos a mis propios modelos de entidades (o más bien, tengo un patrón de repositorio, que se acumula e IQueryable eso hará todo esto).Linq a SQL OrderBy, problema al usar enums

Todo funciona bien, excepto cuando intento aplicar un OrderBy (fuera del repositorio) en una propiedad que he asignado desde short/smallint a una enumeración.

Éstos son los bits de código relevantes:

public class Campaign 
{ 
    public long Id { get; set; } 
    public string Name { get; set; } 
    .... 
    public CampaignStatus Status { get; set; } 
    ... 
} 
public enum CampaignStatus : short { 
    Active, 
    Inactive, 
    Todo, 
    Hidden 
} 
public class SqlCampaignRepository : ICampaignRepository 
{ 
... 
    public IQueryable<Campaign> Campaigns() 
    { 
     DataContext db = new DataContext(); 
     return from c in db.Campaigns 
       select new Campaign 
        { 
         Id = c.Id, 
         Name = c.Name, 
         ... 
         Status = (CampaignStatus)c.Status, 
         ... 
        }; 
    } 
} 

Y luego en otros lugares

SqlCampaignRepository rep = new SqlCampaignRepository(); 
var query = rep.Campaigns().OrderBy(c => c.Status); 

Esto desencadena la siguiente excepción: System.ArgumentException era controlada por el código de usuario mensaje = "El argumento ' valor 'era el tipo incorrecto. Se esperaba' IQMedia.Models.CampaignType '. Actual' System.Int16 '. " Fuente = "System.Data.Linq" StackTrace: System.Data.Linq.SqlClient.SqlOrderExpression.set_Expression ved (valor EnunciadoSql OperadorCompatible EnunciadoParamétricoOConstante) ved System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitSelect (SqlSelect seleccionar) Ved System.Data.Linq.SqlClient.SqlVisitor.Visit (nodo sqlnode) System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitIncludeScope ved (alcance SqlIncludeScope) ...

(lo de la danesa allí , ved = por/a).

He intentado encasillar el estado a abreviar en la expresión orderBy, pero eso no lo ayuda, lo mismo si lo echo al tipo de enumeración real también.

Cualquier ayuda para solucionar esto es muy apreciada.

Respuesta

3

¿Puede especificar el tipo CampaignStatus directamente en su DataContext a través del diseñador? De esta forma, el valor se asigna automáticamente al enum.

1

¿Cuál es la relación entre la clase Campaign y Campaigns? Si Campaigns devuelve el conjunto del objeto Campaign, tenga en cuenta que normalmente no puede select new una entidad mapeada.

Me pregunto si funcionaría mejor si hiciera el OrderBy antes del Select?

Un truco final podría ser crear un compilable falso [Function], usando triviales TSQL. Por ejemplo, ABS podría ser suficiente. es decir, algo así como (el contexto):

[Function(Name="ABS", IsComposable=true)] 
    public int Abs(int value) 
    { // to prove not used by our C# code... 
     throw new NotImplementedException(); 
    } 

Entonces prueba:

.OrderBy(x => ctx.Abs(x.Status)) 

no he probado lo anterior, pero puede darle una oportunidad más adelante ... funciona para algunos otros similares casos, sin embargo.

Vale la pena probarlo ...

0

Mi DataContext tiene su propia clase de entidad denominada Campaña, (que viven en un espacio de nombres diferentes, por supuesto). Además, la columna de estado se guarda como una pequeña imprecisión en la base de datos, y el espacio de nombres de la entidad LINQ tiene su tipo listado como un corto (System.Int16).

El orden SÍ funciona si lo aplico en la consulta en mi repositorio; esto es parte de una cosa más grande, y la idea es NO tener el repositorio aplicando ningún tipo, filtrado o algo así, pero simplemente correlaciona las clases de entidad de base de datos con las mías. Este ejemplo es obviamente un poco sin sentido en el cual es una asignación directa, pero en algunos casos también tengo una localización agregada.

También olvidé agregar - la excepción obviamente no ocurre hasta que intento ejecutar la consulta (es decir, llamar a ToList o enumerar sobre la colección).

En el panorama general, este método está siendo utilizado por una clase de servicio que se supone que debe agregar filtrado, clasificación y todo eso, y el objetivo de todo esto es separar las cosas un poco, pero también permitir transición fácil a una base de datos diferente, o una OR/M diferente, más adelante, si ese fuera el deseo.

Ah no vi ese último bit hasta después de responder: todavía no he tenido experiencia en el uso del atributo Función, pero no tendré acceso al contexto de datos en la clase en la que se supone que debo aplicar la ordenación.