views:

67

answers:

2

Why can't I return as a new custom class (cms.bo.Site) which implements ISite?

public IQueryable<ISite> GetSites()
{
    return (from site in Db.Sites select new cms.bo.Site(site.id, site.name));
}
+4  A: 

Basically LINQ to SQL doesn't know what that constructor will do - it wants to try to convert that into a SQL query, but doesn't know how. Do you need to be able to add extra bits to the query afterwards? If not, you could do:

public IEnumerable<ISite> GetSites()
{
    return Db.Sites.Select(x => new { x.id, x.name }) // Project in SQL
                   .AsEnumerable() // Do the rest in process
                   .Select(x => new cms.bo.Site(x.id, x.name))
                   .Cast<ISite>(); // Workaround for lack of covariance
}

EDIT: I had missed the variance aspect, and was assuming the query was failing at execution time. It's definitely worth trying just the call to Cast<ISite>() as per tvanfosson's answer - but if that doesn't work, try the above :)

Jon Skeet
Great Answer again Jon!
Matias
@Jon, I this wouldn't work because of generic type covariance: `IEnumerable<Site>` to `IEnumerable<ISite>`
bruno conde
Won't that return an IQyueryable<Site>, not an IQueryable<ISite>?
tvanfosson
Good points - fixing!
Jon Skeet
thanks guys and got it working with IQueryable. my head feels light again
monkeylee
+3  A: 

Try this:

    return Db.Sites
             .ToList()
             .Select( s => new cms.bo.Site( s.id, s.name ) )
             .Cast<ISite>()
             .AsQueryable();
tvanfosson
I don't think you need the call to AsQueryable do you?
Jon Skeet
Don't have access to VS right now so I can't verify, but I think it might want to return it as IEnumerable<ISite> instead of IQueryable<ISite> otherwise. That's probably ok, though since the query needs to be materialized in order to create the Site class, but it would change the return type of the method.
tvanfosson