我正在使用泛型实现规范模式,并尝试动态地将标准应用于映射实体的投影简单(未映射)版本。一般来说,它工作得很好,但是一旦我在表达式之后添加Select
并应用,Linq 就会在本地计算表达式Where
。
如果我将其构建为局部变量并传递给相同的Where
.
这是简化的相关代码片段:
public interface ISomeable
{
string Some { get; set; }
}
public static Expression<Func<T, bool>> GetCriteria<T>() where T : class, ISomeable
{ return e => (e.Some == "Hello"); }
...
Expression<Func<MySimpleEntity, bool>> someCriteria = e => (e.Some == "Hello");
Expression<Func<MySimpleEntity, bool>> someCriteria2 = GetCriteria<MySimpleEntity>();
var query = db.Entities
.Select(s => new MySimpleEntity { Id = s.Id, Some = s.Some });
// if this Select is removed and MySimpleEntity in both expressions replaced with MyFullEntity,
// the issue disappears
// this succeeds
var filteredQueryResults = query.Where(someCriteria).ToList();
// at this point, someCriteria2 is set to the same e => (e.Some == "Hello");
// this fails: why is it evaluated locally and not in SQL? <-----
filteredQueryResults = query.Where(someCriteria2).ToList();
// results in a warning:
/*
* 'Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning:
* The LINQ expression 'where (new MySimpleEntity() {Id = [s].Id, Some = [s].Some}.Some == "Hello")'
* could not be translated and will be evaluated locally.'.
*/
如何让它生成正确的 SQL 而不是本地评估someCriteria2?
我怀疑我需要某种类型的选角,但不确定在哪里。两者在调试器中看起来完全相同,所以我不知道为什么 Linq 会以不同的方式对待它们someCriteria。someCriteria2
我创建了一个最小的 .Net Core Console 应用程序来重现该案例。完整的要点在这里:
https://gist.github.com/progmars/eeec32a533dbd2e1f85e551db1bc53f8
NuGet 依赖项: Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.6" Microsoft.Extensions.Logging" Version="2.2.0" Microsoft.Extensions.Logging.Console" Version="2.2.0"
一些解释:
这与同一个查询执行两次这一事实无关。如果我注释掉第一个,query.Where(someCriteria).ToList()第二个调用someCriteria2仍然无法生成有效的 SQL。但是,如果我用第二个查询替换someCriteria2为someCriteria并让它运行,我会在控制台中得到两个完全有效的 SQL 查询。因此,这一切都与泛型someCriteria2和Select投影有关 - 由于某种原因,Linq 不会以相同的方式对待这两个变量,即使编译器(和调试器监视)认为它们是相同的确切类型。
慕姐8265434
慕婉清6462132
相关分类