【发布时间】:2011-09-19 15:42:30
【问题描述】:
对不起我糟糕的英语。
我正在尝试扩展我的 EF 模型(使用 LinqKit)。
只要我使用单个实体表达式,我就没有任何问题,但如果我想使用混合表达式,我就会卡住。
例如,类似这样的 post-of-post 类...
partial class vit_post
{
//[...]
public static Expression<Func<vit_post, bool>> HasMetas(IEnumerable<MetaFilter> metaArgs)
{
var resultsInner = PredicateBuilder.True<vit_post>();
resultsInner.And(p=>p.vit_postmeta.Any(pm => (pm.hide == false)));
foreach (var metaArg in metaArgs)
{
var mf = metaArg;
resultsInner.And(p=>p.vit_postmeta.Any(pm => (pm.meta_key == mf.MetaKey && mf.Compare(pm.meta_value))));
if (mf.ChildrenMetaFilters != null)
{
Expression<Func<vit_post, bool>> resultsInner2;
switch (mf.LogicalOperator)
{
case LogicalOperators.AND:
resultsInner2 = PredicateBuilder.True<vit_post>();
resultsInner = resultsInner2.And(HasMetas(mf.ChildrenMetaFilters));
break;
case LogicalOperators.OR:
resultsInner2 = PredicateBuilder.False<vit_post>();
resultsInner = resultsInner2.Or(HasMetas(mf.ChildrenMetaFilters));
break;
}
}
}
return resultsInner;
}
//[...]
}
...用表达式 HasMetas 扩展实体“vit_post”。
使用这个 sn-p,我得到了实体的一个子集,正如预期的那样:
public SearchResults GetResults()
{
var query = dbc.vit_posts.AsExpandable();
//[...]
if (SearchArgs.Metas != null)
{
var postsbycontent = vit_post.HasMetas(SearchArgs.Metas);
outer = Data.Utility.And(outer, postsbycontent);
}
//[...]
query = query.Where(outer);
var searchResults = new SearchResults
{
Items = searchResultsItems
};
return searchResults;
}
但是如果我尝试将这个表达式移动到像这样的“vit_postmeta”实体:
partial class vit_postmeta
{
//[...]
var resultsInner = PredicateBuilder.True<vit_postmeta>();
resultsInner.And(pm => (pm.hide == false));
foreach (var metaArg in metaArgs)
{
var mf = metaArg;
resultsInner.And(pm => (pm.meta_key == mf.MetaKey && mf.Compare(pm.meta_value)));
if (mf.ChildrenMetaFilters != null)
{
Expression<Func<vit_postmeta, bool>> resultsInner2;
switch (mf.LogicalOperator)
{
case LogicalOperators.AND:
resultsInner2 = PredicateBuilder.True<vit_postmeta>();
resultsInner = resultsInner2.And(HasMetas(mf.ChildrenMetaFilters));
break;
case LogicalOperators.OR:
resultsInner2 = PredicateBuilder.False<vit_postmeta>();
resultsInner = resultsInner2.Or(HasMetas(mf.ChildrenMetaFilters));
break;
}
}
}
return resultsInner;
//[...]
}
我的想法是保留 vit_post 中的原始方法并像这样进行更改:
partial class vit_post
{
//[...]
public static Expression<Func<vit_post, bool>> HasMetas(IEnumerable<MetaFilter> metaArgs)
{
var resultsInner = PredicateBuilder.True<vit_post>();
resultsInner.And(p=>p.vit_postmeta.HasMetas(metaArgs));
return resultsInner;
}
//[...]
}
但我不能这样做,因为“'vit_postmeta' 不包含'HasMetas' 的定义,并且找不到接受'vit_postmeta' 类型的第一个参数的扩展方法'HasMetas'”。
我知道我遗漏了一些东西,但我找不到什么。
更新
我找到了另一种解决方案(也许也是正确的解决方案),在各个实体部分类中实现我的所有表达式。 例如,vit_post 具有与 vit_posts 的表相关的所有表达式,而 vit_postmeta 具有与 vit_postmeta 的表相关的所有表达式。
然后,我的 Search 类对每个实体都有一个私有方法。比如:
private IQueryable<vit_post> QueryPosts()
{
IQueryable<vit_post> queryPosts = VITContext.vit_posts.AsExpandable();
Expression<Func<vit_post, bool>> outerPredicate = PredicateBuilder.True<vit_post>();
if (!_searchArgs.IncludeExpiredPosts)
{
Expression<Func<vit_post, bool>> postsByExpiration = vit_post.ExcludeExpired();
outerPredicate = Data.Utility.And(outerPredicate, postsByExpiration);
}
if (_searchArgs.LocaleCode != null)
{
Expression<Func<vit_post, bool>> postsByLanguage = vit_post.HasLocaleCode(_searchArgs.LocaleCode);
outerPredicate = Data.Utility.And(outerPredicate, postsByLanguage);
}
[...]
}
然后 GetResults() 函数调用所有这些方法并加入它们:
internal string GetResults()
{
IQueryable<vit_post> queryPosts = QueryPosts();
if (_searchArgs.Metas != null)
{
IEnumerable<vit_postmeta> queryMetas = QueryMetas();
queryPosts = from p in queryPosts
join m in queryMetas
on new {id = p.ID, loc = p.locale} equals new {id = m.post_id, loc = m.locale}
select p;
}
}
这样我可以使查询工作,但我仍然不确定这是正确的方法。
【问题讨论】:
-
是什么让你觉得你的英语“很糟糕”?
-
阿杜奇:有时是…… :)
-
GertArnold:是的,vit_post 与 vit_postmeta 有 1-n 关系(表格的设计与 wordpress 表格非常相似)。
标签: linq c#-4.0 entity-framework-4 linqkit