I am having some issues with using the OrderBy extension method on a LINQ query when it is operating on an enum type. I have created a regular DataContext using visual studio by simply dragging and dropping everything onto the designer. I have then created seperate entity models, which are simply POCO's, and I have used a repository pattern to fetch the data from my database and map them into my own entity models (or rather, I have a repository pattern, that builds up and IQueryable that'll do all this).
Everything works just fine, except when I try to apply an OrderBy (outside of the repository) on a property that I have mapped from short/smallint to an enum.
Here are the relevant code bits:
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,
...
};
}
}
And then elsewhere
SqlCampaignRepository rep = new SqlCampaignRepository();
var query = rep.Campaigns().OrderBy(c => c.Status);
This triggers the following exception: System.ArgumentException was unhandled by user code Message="The argument 'value' was the wrong type. Expected 'IQMedia.Models.CampaignType'. Actual 'System.Int16'." Source="System.Data.Linq" StackTrace: ved System.Data.Linq.SqlClient.SqlOrderExpression.set_Expression(SqlExpression value) ved System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitSelect(SqlSelect select) ved System.Data.Linq.SqlClient.SqlVisitor.Visit(SqlNode node) ved System.Data.Linq.SqlClient.SqlBinder.Visitor.VisitIncludeScope(SqlIncludeScope scope) ...
(sorry about the danish in there, ved = by/at).
I have tried typecasting the Status to short in the orderBy expression, but that doesn't help it, same if i cast it to the actual enum type as well.
Any help fixing this is greatly appreciated!
This method performs a stable sort; that is, if the keys of two elements are equal, the order of the elements is preserved.
The OrderBy() Method, first sort the elements of the sequence or collection in ascending order after that ThenBy() method is used to again sort the result of OrderBy() method in ascending order.
No they cannot. They are limited to numeric values of the underlying enum type.
LINQ includes following sorting operators. Sorting Operator. Description. OrderBy. Sorts the elements in the collection based on specified fields in ascending or decending order.
Can you specify the type CampaignStatus
directly in your DataContext
trough the designer? This way the value is automatically mapped to the enum
.
What is the relationship between the Campaign
class and Campaigns
? If Campaigns
returns the set of Campaign
object, note you can't normally select new
a mapped entity.
I wonder if it would work any better if you did the OrderBy before the Select?
One final trick might be to create a fake composable [Function]
, using trivial TSQL. For example, ABS
might be enough. i.e. something like (on the context):
[Function(Name="ABS", IsComposable=true)]
public int Abs(int value)
{ // to prove not used by our C# code...
throw new NotImplementedException();
}
Then try:
.OrderBy(x => ctx.Abs(x.Status))
I haven't tested the above, but can give it a go later... it works for some other similar cases, though.
Worth a shot...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With