How do you cast a LinqToSql Table<TEntity> as a Table<IEntity> where TEntity : IEntity?
I'm trying to use DbLinq with a SQLite database, but I'm running into a problem when I try to cast an ITable
as a Queryable<TEntity>
.
There is a known bug in DbLinq (Issue 211), which might be the source of my problem, but I wanted to make sure my开发者_运维技巧 code is sound and, if it is, find out if there might be something I can do to work around the bug.
Here is the generic repository method that attempts to do the cast:
public IQueryable<TEntity> GetAll()
{
return Table.Cast<TEntity>(); // Table is an ITable
}
This compiles, but if I pass in the interface IPerson
for TEntity
and the type of the entities in the table is Person
(where Person : IPerson
), I'm getting this error from DbLinq:
S0133: Implement QueryMethod Queryable.Cast.
Why am I trying to do this?
I have a library project that doesn't know the type of the entity until runtime, but it does know the interface for the entity. So, I'm trying to cast to the interface type so that my library project can consume the data.
Questions:
- Am I attempting an impossible cast or is this definitely a bug in DbLinq?
- How else could I go about solving my problem?
Update
I reworked my repository class so it now takes a TEntity
and a TEntityBase
, where TEntity
is the actual type of the entity, and TEntityBase
is the interface that I'm trying to cast to. Importantly, I now have the following where
clause in my class definition:
where TEntity : class, TEntityBase
This allows me to store my Table
property as a Table<TEntity>
instead of an ITable
, which allows me to use AsEnumerable()
(as Stephen suggested). Here is the revised method:
public IEnumerable<TEntityBase> GetAll()
{
return Table.AsEnumerable().Select(e => (TEntityBase)e);
}
And so far, that seems to do the trick.
It sounds like a bug, but understand that implementing a LINQ provider is an absolutely huge endeavor. Even (Microsoft's) LINQ to SQL and LINQ to Entities have their own restrictions on exactly which LINQ queries/operations they support or do not support.
If returning IEnumerable<T>
is acceptable, then you could work around the lack of support for Queryable.Cast
by calling AsEnumerable
before calling Cast
. However, this restricts how your DAL can be used: since IQueryable<T>
is no longer returned, further queries (e.g., Where
clauses) won't be passed through to the DB layer.
I agree it sounds like a bug. You could try the following which will do the same thing
return Table.Select<TEntity>(tbl => (TEntity)tbl)
You might have to add a where : ITable to the method definition as well.
精彩评论