我对 Entity Framework(目前使用 v4.1 开发)还很陌生,所以我可能会以完全错误的方式来解决这个问题,所以我欢迎任何指导。
我目前有两个类:Item只有几个简单的字段,FavouriteItem包含对项目和用户的引用(但用户关系与讨论无关)。该项目有一个可为空的DateVisible字段,我将其用作标志来指示是否应显示项目。
为了获得可见项目的列表,我使用了一个简单的查询:
var items = itemRepository
.QueryAll()
.Where(i => i.DateVisible <= DateTime.Now)
显然 QueryAll 返回一个 IQueryable。这是一个简单的示例,因为条件稍微复杂一些,但它说明了我的问题。
接下来,如果我想返回可见项目的收藏列表,那么我可以执行类似的查询:
var favourites= favouriteRepository
.QueryAll()
.Where(f => f.Item.DateVisible <= DateTime.Now)
这工作正常。但是,代码是重复的。所以我想做的是以某种方式使这段代码更加中心化——因为我即将添加一个再次具有 Item 属性的FollowItem类,所以我不得不再次重复代码——不好。
我开始为项目列表创建一个表达式,效果很好:
public static Expression<Func<Item, bool>> IsVisibleExpression<Item>()
{
return item => item.DateVisible != null &&
item.DateVisible <= DateTime.Now;
}
public static IQueryable<Item> WhereVisible<Item>(this IQueryable<Item> queryable)
{
return queryable.Where(Item.IsVisibleExpression());
}
var items = itemRepository
.QueryAll()
.WhereVisible()
同样,我可以为每个类创建这些表达式:
public static Expression<Func<FavouriteItem, bool>> IsVisibleExpression<FavouriteItem>()
{
return favourite => favourite.Item.DateVisible != null &&
favourite.Item.DateVisible <= DateTime.Now;
}
但这又只是重复了代码。有没有办法在它们之间使用相同的代码。我知道我可以在 上加入itemRepository.QueryAll().WhereVisible()
,但是没有办法做到这一点,而不涉及在任何地方这样做吗?
更新:我尝试为类创建一个接口:
public interface IEntityWithItem
{
Item Item { get; set; }
}
并为它创建一个表达式:
public static IQueryable<TEntity> WhereItemVisible<TEntity>(this IQueryable<TEntity> queryable) where TEntity : IEntityWithItem
{
return queryable.Where(ui => ui.Item.DateVisibleFrom != null &&
ui.Item.DateVisibleFrom.Value <= DateTime.Now);
}
我打来的电话:
// Get the favourites
var favourites = favouriteItemRepository.QueryAll()
.WhereItemVisible()
.Where(favourite => favourite.UserId == user.Id);
但它给出了错误:“无法将类型'FavouriteItem'转换为类型'IEntityWithItem'。LINQ to Entities 仅支持转换实体数据模型原始类型。 ”