我首先使用数据库使用Entity Framework自动生成以下两个类;
public partial class UserXml
{
public UserXml()
{
this.UserXmlHotel = new HashSet<UserXmlHotel>();
}
public long UserId { get; set; }
public string Password { get; set; }
public bool Enabled { get; set; }
public byte FailedAttempt { get; set; }
public virtual User User { get; set; }
public virtual UserXmlIp UserXmlIp { get; set; }
public virtual ICollection<UserXmlHotel> UserXmlHotel { get; set; }
}
和
public partial class UserCustomer
{
public UserCustomer ()
{
this.UserCustomerHotel = new HashSet<UserCustomerHotel >();
}
public long UserId { get; set; }
public bool Enabled { get; set; }
public string Password { get; set; }
}
然后我创建了以下类;
public partial class UserXml : IUser
{
}
public partial class UserCustomer : IUser
{
}
public static class EntityExtensions
{
public static IQueryable<T> Enabled<T>(this IQueryable<T> source) where T : IUser
{
return source.Where(x => x.Enabled);
}
}
我的界面为;
public interface IUser
{
bool Enabled { get; }
}
我想要做的是使用相同的可重用代码为每个实体组合相同的调用;所以拿
using(var Context = new EscapeEntities())
{
bool bEnabled = Context.UserXml.First(u => u.UserId == iUserId).Enabled;
}
和
using(var Context = new EscapeEntities())
{
bool bEnabled = Context.UserCustomer.First(u => u.UserId == iUserId).Enabled;
}
我想要使用我的EntityExtensions类,但是我无法使用它。有什么指针吗?
答案 0 :(得分:3)
在实现接口的泛型类型上使用表达式时,表达式构建器会向表达式添加强制转换,如下所示:
x => x.Enabled // converts to something like below:
x => ((IUser)x).Enabled
因此,您需要做的是通过将泛型类型定义为类来告诉表达式构建器不添加强制转换表达式,这意味着您的Enabled(...)
扩展方法必须如下所示:
public static IQueryable<T> Enabled<T>(this IQueryable<T> source)
where T : class, IUser // added 'class' constraint
{
return source.Where(x => x.Enabled);
}
另一种方法(需要更多工作)是定义一个ExpressionVisitor
类来删除表达式上的转换,这在stackoverflow answer上有解释。
因此,在此更正后,您可以轻松地使用您的扩展方法:
using(var Context = new EscapeEntities())
{
IQueryable<UserXml> query = Context.UserXml
.Where(u => u.Password == "Foo")).Enabled();
List<UserXml> res = query.ToList();
}
PS 我认为您最好定义另一个额外的“基础”User
表,其中包含两个名为UserXml
和UserCustomer
的子项并将其抽象出来公共列到User
表中,这消除了对额外接口的需求,并且还与面向对象的设计兼容。