我最后得到了一个带有自定义扩展方法的LinqToSql查询。当我尝试linq2sql尝试生成sql语句时,这个扩展方法是错误的。
方法 'System.Collections.Generic.IList
1[System.String] ToListIfNotNullOrEmpty[String](System.Collections.Generic.IEnumerable
1 [System.String])' 没有受支持的SQL翻译。
public static IList<T> ToListIfNotNullOrEmpty<T>(this IEnumerable<T> value)
{
return value.IsNullOrEmpty()
? null
: (value is IList<T> ? value as IList<T> : new List<T>(value));
}
public IQueryable<Models.Post> GetPosts()
{
var dataLoadOptions = new DataLoadOptions();
dataLoadOptions.LoadWith<Post>(x => x.PostTags);
dataLoadOptions.LoadWith<PostTag>(x => x.Tag);
_sqlDatabase.LoadOptions = dataLoadOptions;
return from p in _sqlDatabase.Posts
select new Models.Post
{
PostId = p.PostId,
CommentList = (from c in p.Comments
select new Models.Comment
{
PostId = c.PostId,
< ... stuff snipped ... >
}).ToListIfNotNullOrEmpty(),
< ... more stuff snipped ... >
TagList = (from t in p.PostTags
select t.Tag.Description).ToListIfNotNullOrEmpty(),
};
}
通常情况下,我最后会有一个ToList()方法,但如果列表为空,我想返回一个空对象。因此我的扩展方法。
有人可以建议我应该如何解决这个问题吗?
答案 0 :(得分:2)
如果您使用IQueriable<T>
代替IEnumerable<T>
制作扩展方法,则可以控制查询执行的时间:
public static IList<T> ToListIfNotNullOrEmpty<T>(this IQueryable<T> value)
{
var results = value.Provider.Execute<IEnumerable<T>>(value.Expression);
return results == null || results .Count() == 0
? null
: results.ToList();
}
答案 1 :(得分:1)
你试过这个:
return _postRepository.Comments.ToList().ToNullIfEmpty();
使用扩展方法:
public static IList<T> ToNullIfEmpty<T>(this List<T> value)
{
return value.IsNullOrEmpty() ? null: value;
}
问题是这一点:
TagList = (from t in p.PostTags
select t.Tag.Description).ToListIfNotNullOrEmpty()
如果你有这个,那么它会起作用:
select new Models.Post
{
....
}.ToList().ToNullIfEmpty();
或者您可以尝试更改扩展方法以扩展IQueryable,就像其他评论者建议的那样。
答案 2 :(得分:0)
我遇到了同样的问题。问题是您不能在延迟的linq2sql表达式中使用扩展方法。这是因为IQueryable
提供程序在执行查询时会尝试将表达式树中的所有方法转换为SQL。它无法区分您的方法和linq2sql原生的方法之间的区别。因此问题。
解决方案是将方法添加到将扩展本机linq2sql类而不是扩展方法的分部类。
编辑:我正在为代码添加建议的更改
public IQueryable<Models.Post> GetPosts()
{
var dataLoadOptions = new DataLoadOptions();
dataLoadOptions.LoadWith<Post>(x => x.PostTags);
dataLoadOptions.LoadWith<PostTag>(x => x.Tag);
_sqlDatabase.LoadOptions = dataLoadOptions;
return from p in _sqlDatabase.Posts
select new Models.Post
{
PostId = p.PostId,
CommentList = p.GetCommentList(),
< ... more stuff snipped ... >
TagList = (from t in p.PostTags
select t.Tag.Description).ToListIfNotNullOrEmpty()
};
}
然后我会在部分类
中使用GetCommentList()
方法
public partial class Post
{
public List<Comment> GetCommentList()
{
List<Commment> resultList = from this.Comments etc...
< ... put the select code here ... >
if(resultList.Count > 0)
return resultList;
return null;
}
}