Извините за мой ужасный английский.
Я пытаюсь расширить мою модель EF (с помощью LinqKit).
Пока я работаю с выражениями из отдельных сущностей, у меня нет никаких проблем, но если я хочу работать со смешанными выражениями, я просто застреваю.
Например, класс вроде почтового отправления, подобный этому ...
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;
}
//[...]
}
... расширяет сущность "vit_post" с помощью выражения HasMetas.
Используя этот фрагмент, я получаю подмножество сущностей, как и ожидалось:
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», а метод расширения «HasMetas», принимающий первый аргумент типа «vit_postmeta», не найден ».
Я что-то упускаю, я знаю, но не могу найти, что.
UPDATE
Я нашел альтернативное решение (и, возможно, правильное тоже), реализующее все мое выражение в соответствующих частичных классах сущностей.
Например, у vit_post есть все выражения, относящиеся к таблице vit_posts, а у vit_postmeta есть все выражения, относящиеся к таблице vit_postmeta.
Мой класс поиска затем имеет закрытый метод для каждой сущности. Что-то вроде:
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;
}
}
Таким образом, я могу заставить запрос работать, но я все еще не уверен, что это правильный способ сделать это.