好的我在這裏有很多關於這種性質的問題,但沒有一個能夠完全或正確地解決這個問題。Linq to Entities and complex type casting
讓我們假設我有以下代碼...
public interface IHaveRoles {
ICollection<Role> Roles { get;set; }
}
public class Foo : IHaveRoles {
public ICollection<Role> Roles { get;set; }
}
public class Bar { }
...然後我有這樣的方法......
public override IQueryable<T> GetAll()
{
return base.GetAll();
}
到該方法
我想添加一個檢查這可能會導致我動態地添加一個簡單的where子句到我的IQueryable ...
if(typeof(IHaveRoles<Role>).IsAssignableFrom(typeof(T))) {
return base.GetAll()
.Where(i => i.Roles.Any(r => r.Users.Any(u => u.Id == User.Id)));
}
... 這是一個非常簡單的where子句,如果我知道T在設計時是什麼,那麼這將是一個非問題。
然而,在澆鑄result
到IQueryable<IHaveRoles>
是不是因爲當我完成追加我的條款我不能再轉換回一個IQueryable<T>
作爲IHaveRoles
一個選項不是T
那麼,如何做一個子類型我們解決這個問題,同時保留返回一個IQueryable<T>
並沒有違法強制轉換的能力,如在一些像這樣的其他問題給出的答案...
Cast Entity to Implemented Interface in a Generic Method Using LINQ for Entity Framework
LINQ-to-entities casting issue
...在避免與EF不支持不EDM基本類型的問題的方式......
LINQ to Entities only supports casting EDM primitive or enumeration types with IEntity interface
編輯:一些測試,實現...
public override IQueryable<T> GetAll()
{
var result = base.GetAll();
if (typeof(IHaveRoles).IsAssignableFrom(typeof(T)) && !AuthInfo.SignatureIsValid)
{
// tried implementations that don't work ...
// InvalidCastException (CLR can't cast an IQueryable<IHaveRoles> to a IQueryable<T>
var queryableRoleSecured = ((IQueryable<IHaveRoles>)result);
result = (IQueryable<T>)queryableRoleSecured
.Where(i => i.Roles.Any(r => User.Roles.Contains(r)));
// NotSupportedException (EF won't accept this kind of casting)
result = result
.Where(i => ((IHaveRoles)i).Roles.Any(r => r.Users.Any(u => u.Id == User.Id)));
}
return result;
}