gpt4 book ai didi

c# - Entity Framework - 类似属性的表达

转载 作者:行者123 更新时间:2023-11-30 18:36:51 27 4
gpt4 key购买 nike

我对 Entity Framework 还很陌生(目前使用 v4.1 开发),所以我可能会以完全错误的方式解决这个问题,所以我欢迎任何指导。

我目前有两个类:Item,它只有几个简单的字段,而 FavouriteItem 包含对项目和用户的引用(但用户关系是'与讨论有关)。该项目有一个可为 null 的 DateVisible 字段,我将其用作标志以指示是否应显示该项目。

为了获得可见项目的列表,我使用了一个简单的查询:

var items = itemRepository
.QueryAll()
.Where(i => i.DateVisible <= DateTime.Now)

显然 QueryAll 返回一个 IQueryable。这是一个简单的示例,因为条件稍微复杂一些,但它证明了我的问题。

接下来,如果我想返回可见项目的收藏夹列表,那么我可以执行类似的查询:

var favourites= favouriteRepository
.QueryAll()
.Where(f => f.Item.DateVisible <= DateTime.Now)

这很好用。但是,代码是重复的。所以我想做的是以某种方式使这段代码更集中——因为我要添加一个 FollowingItem 类,它又具有一个 Item 属性,所以我不得不重复代码再次 - 不好。

我开始为项目列表创建一个表达式,效果很好:

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() 上做一个连接,但是有没有一种方法可以做到这一点而不需要在任何地方都这样做?

更新:我尝试为这些类创建一个接口(interface):

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 仅支持转换实体数据模型基元类型。

最佳答案

据我所知,没有简单的方法可以实现这一点,但是请看一下 PredicateBuilder,它确实解决了其中的一些问题:http://www.albahari.com/nutshell/predicatebuilder.aspx .

基本思想是您定义具有公共(public)属性的接口(interface),这允许您定义受限于该接口(interface)的通用表达式。

首先定义这些接口(interface):

public interface IHaveItem
{
Item Item {get;}
}

public interface IDateVisible
{
DateTime? DateVisible {get;}
}

这将允许您以通用方式编写查询表达式,至少获得一些重用:

public static Expression<Func<T,bool>> IsVisible<T>(DateTime now) 
where T:IHaveItem
{
return x => x.Item.DateVisible != null &&
x.Item.DateVisible < now;
}

但是,您仍然无法轻松实现 x.DateVisiblex.Item.DateVisible 等表达式之间的重用。

更新:事实证明,在生成的表达式树中添加了“不必要的”转换操作,然后在转换为 SQL 时 Entity Framework 提供程序不支持这些操作。

您可以应用与 this question 中类似的技巧“手动”删除这些不必要的转换操作。虽然恕我直言,但变得有点毛茸茸......

关于c# - Entity Framework - 类似属性的表达,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13376326/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com