Linq to sql 本地序列不能用于LINQ到SQL的实现
当我试图生成类MappeItem的列表时,出现了一个错误,请参见下面的。简而言之,下面的代码示例尝试按类别、日期范围和SKU查找产品。我的要求是,用户应该能够输入一个逗号分隔的SKU列表,搜索是查找任何SKU以用户输入的SKU之一开头的产品。当我运行代码时,我得到了 除了Contains()运算符外,查询运算符的LINQ to SQL实现中不能使用局部序列 缩写顺序如下: 将以逗号分隔的SKU字符串转换为字符串列表Linq to sql 本地序列不能用于LINQ到SQL的实现,linq-to-sql,contains,startswith,Linq To Sql,Contains,Startswith,当我试图生成类MappeItem的列表时,出现了一个错误,请参见下面的。简而言之,下面的代码示例尝试按类别、日期范围和SKU查找产品。我的要求是,用户应该能够输入一个逗号分隔的SKU列表,搜索是查找任何SKU以用户输入的SKU之一开头的产品。当我运行代码时,我得到了 除了Contains()运算符外,查询运算符的LINQ to SQL实现中不能使用局部序列 缩写顺序如下: 将以逗号分隔的SKU字符串转换为字符串列表 string sku = TextSKU.Text; List<strin
string sku = TextSKU.Text;
List<string> skuList = sku.Split(new char[] { ',' }).ToList();
这是我生成结果的查询
List<MappedItem> widgetItems = (from c1 in db.CCRCodes
join pac in db.widgetAssignedCodes on c1.code_id equals pac.code_id
join ph in db.widgetHistories on pac.history_id equals ph.history_id
where ph.contact_dt.Value.Date >= startDate && ph.contact_dt.Value.Date <= endDate &&
(string.IsNullOrEmpty(baanCatFam) || ph.baan_cat_family_code == baanCatFam) &&
(string.IsNullOrEmpty(baanCat) || ph.baan_cat_code == baanCat) &&
(string.IsNullOrEmpty(baanSubCat) || (ph.baan_sub_cat_code == baanSubCat)) &&
(string.IsNullOrEmpty(sku) || skuList.All(sl => ph.product_mod.StartsWith(sl)))
group c1 by c1.code_desc into ct
select new MappedItem
{
ItemDescription = ct.Key.ToUpper(),
ItemCount = ct.Count()
}).OrderByDescending(m => m.ItemCount)
.ToList();
这将标识以skuList中的元素开头的所有SKU,skuList源自用户输入的以逗号分隔的SKU列表。我的问题是,是什么导致了这个错误,并且给出了代码示例,我该怎么做才能避免这些错误。首先-从逻辑上讲,您想要任何错误,而不是所有错误 第二,这是一种构建查询过滤器的糟糕方法。所有这些操作都被发送到数据库中,而用于确定应应用哪些过滤器的信息已经是本地的。显式联接也不好(可以改用关联属性) 接下来,一个助手方法:
public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>(
this IEnumerable<Expression<Func<T, bool>>> filters)
{
Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault();
if (firstFilter == null)
{
Expression<Func<T, bool>> alwaysTrue = x => true;
return alwaysTrue;
}
var body = firstFilter.Body;
var param = firstFilter.Parameters.ToArray();
foreach (var nextFilter in filters.Skip(1))
{
var nextBody = Expression.Invoke(nextFilter, param);
body = Expression.OrElse(body, nextBody);
}
Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param);
return result;
}
公共静态表达式或过滤器组合在一起(
这是(可数过滤器)
{
表达式firstFilter=filters.FirstOrDefault();
if(firstFilter==null)
{
表达式alwaysTrue=x=>true;
始终返回;
}
var body=firstFilter.body;
var param=firstFilter.Parameters.ToArray();
foreach(过滤器中的var nextFilter.Skip(1))
{
var nextBody=Expression.Invoke(nextFilter,param);
body=Expression.OrElse(body,nextBody);
}
表达式结果=表达式.Lambda(body,param);
返回结果;
}
现在把所有这些放在一起:
if (skuFilters.Any()) //this part goes into where it says "TODO"
{
Expression<Func<WidgetHistory, bool>> theSkuFilter = skuFilters.OrTheseFiltersTogether()
query = query.Where(theSkuFilter);
}
if(skuFilters.Any())//此部分进入显示“TODO”的位置
{
表达式Theskuffilter=skuffilters.OrTheseFiltersTogether()
query=query.Where(塞斯克过滤器);
}
IQueryable<WidgetHistory> query = db.widgetHistories
.Where(ph => ph.contact_dt.Value.Date >= startDate
&& ph.contact_dt.Value.Date <= endDate);
if (!string.IsNullOrEmpty(baanCatFam))
{
query = query.Where(ph => ph.baan_cat_family_code == baanCatFam);
}
if (!string.IsNullOrEmpty(baanCat))
{
query = query.Where(ph => ph.baan_cat_code == baanCat);
}
if (!string.IsNullOrEmpty(baanSubCat))
{
query = query.Where(ph => ph.baan_sub_cat_code == baanSubCat);
}
//TODO sku filtering here.
List<MappedItem> widgetItems =
from ph in query
let c1 = ph.widgetAssignedCode.CCRCode
group c1 by c1.code_desc into g
select new MappedItem
{
ItemDescription = g.Key.ToUpper(),
ItemCount = g.Count()
}).OrderByDescending(m => m.ItemCount)
.ToList();
List<Expression<Func<WidgetHistory, bool>>> skuFilters =
skuList.Select<string, Expression<Func<WidgetHistory, bool>>>(skuItem =>
ph => ph.ProductMod.StartsWith(skuItem)
).ToList();
public static Expression<Func<T, bool>> OrTheseFiltersTogether<T>(
this IEnumerable<Expression<Func<T, bool>>> filters)
{
Expression<Func<T, bool>> firstFilter = filters.FirstOrDefault();
if (firstFilter == null)
{
Expression<Func<T, bool>> alwaysTrue = x => true;
return alwaysTrue;
}
var body = firstFilter.Body;
var param = firstFilter.Parameters.ToArray();
foreach (var nextFilter in filters.Skip(1))
{
var nextBody = Expression.Invoke(nextFilter, param);
body = Expression.OrElse(body, nextBody);
}
Expression<Func<T, bool>> result = Expression.Lambda<Func<T, bool>>(body, param);
return result;
}
if (skuFilters.Any()) //this part goes into where it says "TODO"
{
Expression<Func<WidgetHistory, bool>> theSkuFilter = skuFilters.OrTheseFiltersTogether()
query = query.Where(theSkuFilter);
}