IQueryable<Organization> query = context.Organizations;
Func<Reservation, bool> predicate = r => !r.IsDeleted;
query.Select(o => new {
Reservations = o.Reservations.Where(predicate)
}).ToList();
this query throws "Internal .NET Framework Data Provider error 1025" exception but the query below does not.
这个查询抛出“内部。net Framework Data Provider error 1025”异常,但下面的查询没有。
query.Select(o => new {
Reservations = o.Reservations.Where( r => !r.IsDeleted)
}).ToList();
I need to use the first one because I need to check a few if statements for constructing the right predicate. I know that I can not use if statements in this circumstance that is why I pass a delegate as parameter.
我需要使用第一个,因为我需要检查一些if语句来构造正确的谓词。我知道在这种情况下我不能使用if语句,所以我将委托作为参数传递。
How can I make the first query work?
如何进行第一个查询工作?
5 个解决方案
#1
29
While the above answers are true, note that when trying to use it after a select statement one has to call AsQueryable()
explicitly, otherwise the compiler will assume that we are trying to use IEnumerable methods, which expect a Func
and not Expression<Func>
.
虽然上面的答案是正确的,但是请注意,当在select语句之后尝试使用它时,必须显式地调用AsQueryable(),否则编译器将假定我们正在尝试使用IEnumerable方法,它期望一个Func而不是表达式
This was probably the issue of the original poster, as otherwise the compiler will complain most of the time that it is looking for Expression<Func>
and not Func
.
这可能是原始海报的问题,否则编译器会抱怨大部分时间都在寻找表达式
Demo: The following will fail:
演示:以下将失败:
MyContext.MySet.Where(m =>
m.SubCollection.Select(s => s.SubItem).Any(expr))
.Load()
While the following will work:
下面的工作将会:
MyContext.MySet.Where(m =>
m.SubCollection.Select(s => s.SubItem).AsQueryable().Any(expr))
.Load()
#2
24
After creating the bounty (rats!), I found this answer, which solved my problem. (My problem involved a .Any()
call, which is a little more complicated than this question...)
在创造了奖赏(老鼠!)之后,我找到了这个答案,它解决了我的问题。(我的问题涉及a .Any()电话,这比这个问题稍微复杂一点……)
In short, here's your answer:
简而言之,你的答案是:
IQueryable<Organization> query = context.Organizations;
Expression<Func<Reservation, bool>> expr = r => !r.IsDeleted;
query.Select(o => new { Reservations = o.Reservations.Where(expr) })
.ToList();
Read the referenced answer for an explanation of why you need the local variable expr
, and you can't directly reference another method of return type Expression<Func<Reservation, bool>>
.
阅读参考答案,解释为什么需要本地变量expr,而不能直接引用另一种返回类型表达式
#3
16
Thanks for pinging me. I guess I was on the right track after all.
谢谢你联系我。我想我毕竟是在正确的轨道上。
Anyway, to reiterate, LINQ to Entities (thanks to Jon Skeet for correcting me when I got mixed up in my own thought process in the comments) operates on Expression Trees; it allows for a projection to translate the lambda expression to SQL by the QueryProvider
.
无论如何,要重申的是,LINQ to实体(感谢Jon Skeet在我在评论中对我的想法进行了混淆)对表达式树进行了操作;它允许投影将lambda表达式转换为QueryProvider。
Regular Func<>
works well for LINQ to Objects.
普通的Func<>在LINQ to Objects中很好用。
So in this case, when you're using the Entity Framework, any predicate passed to the EF's IQueryable
has to be the Expression<Func<>>
.
在这种情况下,当使用实体框架时,传递给EF的任何谓词都必须是表达式
#4
3
I just experienced this issue in a different scenario.
我只是在不同的情况下经历了这个问题。
I have a static class full of Expression
predicates which I can then combine or pass to an EF query. One of them was:
我有一个充满表达式谓词的静态类,我可以将其合并或传递到EF查询。其中一个是:
public static Expression<Func<ClientEvent, bool>> ClientHasAttendeeStatus(
IEnumerable<EventEnums.AttendeeStatus> statuses)
{
return ce => ce.Event.AttendeeStatuses
.Where(a => a.ClientId == ce.Client.Id)
.Select(a => a.Status.Value)
.Any(statuses.Contains);
}
This was throwing the 1025 error due to the Contains
method group call. The entity framework expected an Expression and found a method group, which resulted in the error. Converting the code to use a lambda (which can be implicitly cast to an Expression) fixed the error
这是由于包含方法组调用导致的1025错误。实体框架期望一个表达式并找到一个方法组,结果导致错误。将代码转换为使用lambda(可以隐式地转换为表达式)来修正错误。
public static Expression<Func<ClientEvent, bool>> ClientHasAttendeeStatus(
IEnumerable<EventEnums.AttendeeStatus> statuses)
{
return ce => ce.Event.AttendeeStatuses
.Where(a => a.ClientId == ce.Client.Id)
.Select(a => a.Status.Value)
.Any(x => statuses.Contains(x));
}
Aside: I then simplified the expression to ce => ce.Event.AttendeeStatuses.Any(a => a.ClientId == ce.Client.Id && statuses.Contains(a.Status.Value));
旁白:然后将表达式简化为ce => . event . attendeestatuse。(= >。ClientId = = ce.Client。Id & & statuses.Contains(a.Status.Value));
#5
0
Had a similar problem. Library of ViewModels that look like this:
有一个类似的问题。像这样的viewmodel库:
public class TagViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public static Expression<Func<SiteTag, TagViewModel>> Select = t => new TagViewModel
{
Id = t.Id,
Name = t.Name,
};
This works:
如此:
var tags = await db.Tags.Take(10).Select(TagViewModel.Select)
.ToArrayAsync();
But, this won't compile:
但是,这不会编译:
var post = await db.Posts.Take(10)
.Select(p => new {
Post = p,
Tags = p.Tags.Select(pt => pt.Tag).Select(TagViewModel.Select)
})
.ToArrayAsync();
Because the second .Select
is a mess - the first one is actually called off of an ICollection, which is not IQueryable, so it consumes that first Expression as a plain Func
, not Expression<Func...
. That returns IEnumerable<...
, as discussed on this page. So .AsQueryable()
to the rescue:
因为第二个。select是一个混乱,第一个是被取消的ICollection,它不是IQueryable,所以它将第一个表达式作为一个普通的Func,而不是表达式
var post = await db.Posts.Take(10)
.Select(p => new {
Post = p,
Tags = p.Tags.Select(pt => pt.Tag).AsQueryable()
.Select(TagViewModel.Select)
})
.ToArrayAsync();
But that creates a new, weirder problem: Either I get Internal Framework...Error 1025, or I get the post variable with a fully loaded .Post
property, but the .Tags
property has an EF proxy object that seems to be used for Lazy-Loading.
但这创造了一个新的更奇怪的问题:要么我得到内部框架……错误1025,或者我用一个完全加载的. post属性获得post变量,但是. tags属性有一个EF代理对象,它似乎是用于延迟加载的。
The solution is to control the return type of Tags, by ending use of the Anonymous class:
解决方案是通过终止使用匿名类来控制标记的返回类型:
public class PostViewModel
{
public Post Post { get; set; }
public IEnumerable<TagViewModel> Tags { get; set; }
Now select into this and it all works:
现在选择这个,所有的工作:
var post = await db.Posts.Take(10)
.Select(p => new PostViewModel {
Post = p,
Tags = p.Tags.Select(pt => pt.Tag).AsQueryable()
.Select(TagViewModel.Select)
})
.ToArrayAsync();
#1
29
While the above answers are true, note that when trying to use it after a select statement one has to call AsQueryable()
explicitly, otherwise the compiler will assume that we are trying to use IEnumerable methods, which expect a Func
and not Expression<Func>
.
虽然上面的答案是正确的,但是请注意,当在select语句之后尝试使用它时,必须显式地调用AsQueryable(),否则编译器将假定我们正在尝试使用IEnumerable方法,它期望一个Func而不是表达式
This was probably the issue of the original poster, as otherwise the compiler will complain most of the time that it is looking for Expression<Func>
and not Func
.
这可能是原始海报的问题,否则编译器会抱怨大部分时间都在寻找表达式
Demo: The following will fail:
演示:以下将失败:
MyContext.MySet.Where(m =>
m.SubCollection.Select(s => s.SubItem).Any(expr))
.Load()
While the following will work:
下面的工作将会:
MyContext.MySet.Where(m =>
m.SubCollection.Select(s => s.SubItem).AsQueryable().Any(expr))
.Load()
#2
24
After creating the bounty (rats!), I found this answer, which solved my problem. (My problem involved a .Any()
call, which is a little more complicated than this question...)
在创造了奖赏(老鼠!)之后,我找到了这个答案,它解决了我的问题。(我的问题涉及a .Any()电话,这比这个问题稍微复杂一点……)
In short, here's your answer:
简而言之,你的答案是:
IQueryable<Organization> query = context.Organizations;
Expression<Func<Reservation, bool>> expr = r => !r.IsDeleted;
query.Select(o => new { Reservations = o.Reservations.Where(expr) })
.ToList();
Read the referenced answer for an explanation of why you need the local variable expr
, and you can't directly reference another method of return type Expression<Func<Reservation, bool>>
.
阅读参考答案,解释为什么需要本地变量expr,而不能直接引用另一种返回类型表达式
#3
16
Thanks for pinging me. I guess I was on the right track after all.
谢谢你联系我。我想我毕竟是在正确的轨道上。
Anyway, to reiterate, LINQ to Entities (thanks to Jon Skeet for correcting me when I got mixed up in my own thought process in the comments) operates on Expression Trees; it allows for a projection to translate the lambda expression to SQL by the QueryProvider
.
无论如何,要重申的是,LINQ to实体(感谢Jon Skeet在我在评论中对我的想法进行了混淆)对表达式树进行了操作;它允许投影将lambda表达式转换为QueryProvider。
Regular Func<>
works well for LINQ to Objects.
普通的Func<>在LINQ to Objects中很好用。
So in this case, when you're using the Entity Framework, any predicate passed to the EF's IQueryable
has to be the Expression<Func<>>
.
在这种情况下,当使用实体框架时,传递给EF的任何谓词都必须是表达式
#4
3
I just experienced this issue in a different scenario.
我只是在不同的情况下经历了这个问题。
I have a static class full of Expression
predicates which I can then combine or pass to an EF query. One of them was:
我有一个充满表达式谓词的静态类,我可以将其合并或传递到EF查询。其中一个是:
public static Expression<Func<ClientEvent, bool>> ClientHasAttendeeStatus(
IEnumerable<EventEnums.AttendeeStatus> statuses)
{
return ce => ce.Event.AttendeeStatuses
.Where(a => a.ClientId == ce.Client.Id)
.Select(a => a.Status.Value)
.Any(statuses.Contains);
}
This was throwing the 1025 error due to the Contains
method group call. The entity framework expected an Expression and found a method group, which resulted in the error. Converting the code to use a lambda (which can be implicitly cast to an Expression) fixed the error
这是由于包含方法组调用导致的1025错误。实体框架期望一个表达式并找到一个方法组,结果导致错误。将代码转换为使用lambda(可以隐式地转换为表达式)来修正错误。
public static Expression<Func<ClientEvent, bool>> ClientHasAttendeeStatus(
IEnumerable<EventEnums.AttendeeStatus> statuses)
{
return ce => ce.Event.AttendeeStatuses
.Where(a => a.ClientId == ce.Client.Id)
.Select(a => a.Status.Value)
.Any(x => statuses.Contains(x));
}
Aside: I then simplified the expression to ce => ce.Event.AttendeeStatuses.Any(a => a.ClientId == ce.Client.Id && statuses.Contains(a.Status.Value));
旁白:然后将表达式简化为ce => . event . attendeestatuse。(= >。ClientId = = ce.Client。Id & & statuses.Contains(a.Status.Value));
#5
0
Had a similar problem. Library of ViewModels that look like this:
有一个类似的问题。像这样的viewmodel库:
public class TagViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public static Expression<Func<SiteTag, TagViewModel>> Select = t => new TagViewModel
{
Id = t.Id,
Name = t.Name,
};
This works:
如此:
var tags = await db.Tags.Take(10).Select(TagViewModel.Select)
.ToArrayAsync();
But, this won't compile:
但是,这不会编译:
var post = await db.Posts.Take(10)
.Select(p => new {
Post = p,
Tags = p.Tags.Select(pt => pt.Tag).Select(TagViewModel.Select)
})
.ToArrayAsync();
Because the second .Select
is a mess - the first one is actually called off of an ICollection, which is not IQueryable, so it consumes that first Expression as a plain Func
, not Expression<Func...
. That returns IEnumerable<...
, as discussed on this page. So .AsQueryable()
to the rescue:
因为第二个。select是一个混乱,第一个是被取消的ICollection,它不是IQueryable,所以它将第一个表达式作为一个普通的Func,而不是表达式
var post = await db.Posts.Take(10)
.Select(p => new {
Post = p,
Tags = p.Tags.Select(pt => pt.Tag).AsQueryable()
.Select(TagViewModel.Select)
})
.ToArrayAsync();
But that creates a new, weirder problem: Either I get Internal Framework...Error 1025, or I get the post variable with a fully loaded .Post
property, but the .Tags
property has an EF proxy object that seems to be used for Lazy-Loading.
但这创造了一个新的更奇怪的问题:要么我得到内部框架……错误1025,或者我用一个完全加载的. post属性获得post变量,但是. tags属性有一个EF代理对象,它似乎是用于延迟加载的。
The solution is to control the return type of Tags, by ending use of the Anonymous class:
解决方案是通过终止使用匿名类来控制标记的返回类型:
public class PostViewModel
{
public Post Post { get; set; }
public IEnumerable<TagViewModel> Tags { get; set; }
Now select into this and it all works:
现在选择这个,所有的工作:
var post = await db.Posts.Take(10)
.Select(p => new PostViewModel {
Post = p,
Tags = p.Tags.Select(pt => pt.Tag).AsQueryable()
.Select(TagViewModel.Select)
})
.ToArrayAsync();