我正在使用LinqKit库,它允许动态组合表达式.
这是编写Entity Framewok数据访问层的纯粹幸福,因为可以选择重复使用和组合多个表达式,这样就可以实现可读和高效的代码.
请考虑以下代码:
private static readonly Expression<Func<Message, int, MessageView>> _selectMessageViewExpr =
( Message msg, int requestingUserId ) =>
new MessageView
{
MessageID = msg.ID,
RequestingUserID = requestingUserId,
Body = ( msg.RootMessage == null ) ? msg.Body : msg.RootMessage.Body,
Title = ( ( msg.RootMessage == null ) ? msg.Title : msg.RootMessage.Title ) ?? string.Empty
};
Run Code Online (Sandbox Code Playgroud)
我们声明了一个投射Message
到的表达式MessageView
(为了清楚起见,我删除了细节).
现在,数据访问代码可以使用此表达式来获取单个消息:
var query = CompiledQueryCache.Instance.GetCompiledQuery(
"GetMessageView",
() => CompiledQuery.Compile(
_getMessagesExpr
.Select( msg => _selectMessageViewExpr.Invoke( msg, userId ) ) …
Run Code Online (Sandbox Code Playgroud) 我在我的数据访问层中使用LINQ to Entities for Entity Framework对象.
我的目标是尽可能多地从数据库中过滤,而不将过滤逻辑应用于内存中的结果.
为此,业务逻辑层将谓词传递给数据访问层.
我的意思是
Func<MyEntity, bool>
Run Code Online (Sandbox Code Playgroud)
所以,如果我直接使用这个谓词,就像
public IQueryable<MyEntity> GetAllMatchedEntities(Func<MyEntity, Boolean> isMatched)
{
return qry = _Context.MyEntities.Where(x => isMatched(x));
}
Run Code Online (Sandbox Code Playgroud)
我得到了例外
[System.NotSupportedException] --- {"LINQ to Entities中不支持LINQ表达式节点类型'Invoke'."}
该问题的解决方案建议使用LINQKit库中的AsExpandable()方法.
但是再次使用
public IQueryable<MyEntity> GetAllMatchedEntities(Func<MyEntity, Boolean> isMatched)
{
return qry = _Context.MyEntities.AsExpandable().Where(x => isMatched(x));
}
Run Code Online (Sandbox Code Playgroud)
我得到了例外
无法将类型为"System.Linq.Expressions.FieldExpression"的对象强制转换为"System.Linq.Expressions.LambdaExpression"
有没有办法在LINQ to Entities查询实体框架对象中使用谓词,以便将其正确转换为SQL语句.
谢谢.
给定一个简单的父/子类结构.我想使用linqkit在父级上应用子lambda表达式.我还希望Lambda表达式由实用程序方法提供.
public class Foo
{
public Bar Bar { get; set; }
}
public class Bar
{
public string Value { get; set; }
public static Expression<Func<Bar, bool>> GetLambdaX()
{
return c => c.Value == "A";
}
}
...
Expression<Func<Foo, bool>> lx = c => Bar.GetLambdaX().Invoke(c.Bar);
Console.WriteLine(lx.Expand());
Run Code Online (Sandbox Code Playgroud)
上面的代码抛出
System.InvalidCastException: Unable to cast object of type
'System.Linq.Expressions.MethodCallExpression' to type
'System.Linq.Expressions.LambdaExpression'.
at LinqKit.ExpressionExpander.VisitMethodCall(MethodCallExpression m)
at LinqKit.ExpressionVisitor.Visit(Expression exp)
at LinqKit.ExpressionVisitor.VisitLambda(LambdaExpression lambda)
at LinqKit.ExpressionVisitor.Visit(Expression exp)
at LinqKit.Extensions.Expand<TDelegate>(Expression`1 expr)
Run Code Online (Sandbox Code Playgroud) 我一直在尝试将LINQKit整合到共享数据访问层中,但是,我遇到了障碍.使用a构造嵌套查询时ExpandableQuery
,表达式解析器无法正确解包ExpandableQuery
并构造有效的SQL查询.抛出的错误如下:
System.NotSupportedException:无法创建"Store"类型的常量值.在此上下文中仅支持基元类型或枚举类型.
通过以下示例程序,我们可以轻松地重建此问题,并且它AsExpandable()
与`table上的调用明显隔离.
class Program
{
static void Main(string[] args)
{
Database.SetInitializer<MyContext>(null);
var cs = MY_CONNECTION_STRING;
var context = new MyContext(cs);
var table = (IQueryable<Store>)context.Set<Store>();
var q = table
.AsExpandable()
.Select(t => new {Id = t.StoreId, less = table.Where(tt => tt.StoreId > t.StoreId) })
.Take(1)
.ToArray();
}
}
public class MyContext : DbContext
{
public MyContext(string connection) : base(connection) {}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Store>();
base.OnModelCreating(modelBuilder);
}
}
[Table("stores")]
public …
Run Code Online (Sandbox Code Playgroud) 我有代码:
var predicate = PredicateBuilder.True<Value>();
predicate = predicate.And(x => x.value1 == "1");
predicate = predicate.And(x => x.value2 == "2");
var vals = Value.AsExpandable().Where(predicate).ToList();
Run Code Online (Sandbox Code Playgroud)
如果我有PredicateBuilder.True<Value>()
,它会带回我的期望,但如果我有PredicateBuilder.False<Value>()
,它会带回0记录.有人可以解释这是什么区别,为什么在一个场景中我得到0记录在另一个我得到我期望的.我已经阅读了PredicateBuilder
这份文件,但有点令人困惑.我觉得这与我Anding
在一起的谓词有关吗?
我正在使用LinqKit的PrediateBuilder类来构建谓词来动态设置过滤器,我希望将嵌套的过滤器组合到另一个.
我已经读过这篇文章了(http://www.albahari.com/nutshell/predicatebuilder.aspx):
这是我的代码:
// The main predicate.
var mainPredicate = PredicateBuilder.True<Document>();
// ... some other conditions to the main predicate here ...
// The inner predicate (combined conditions using OR).
var innerPredicate = PredicateBuilder.False<Document>();
foreach (var period in periods)
{
var p = period;
innerPredicate =
innerPredicate.Or(
d =>
(d.Date >= p.DateFrom && d.Date <= p.DateTo));
}
mainPredicate = mainPredicate.And(innerPredicate);
documents = this.ObjectSet.AsExpandable().Where(mainPredicate).ToList();
Run Code Online (Sandbox Code Playgroud)
我正在组合我的两个谓词,就像在文档中解释的那样.但是,我得到了这个例外:
参数"f"未绑定在指定的LINQ to Entities查询表达式中
我首先想到内部谓词在与主谓词组合之前必须进行扩展,所以我改变了我的组合代码来添加对内部谓词Expand
方法的调用,如下所示:
mainPredicate = …
Run Code Online (Sandbox Code Playgroud) 我想使用LinqKit的PredicateBuilder并将谓词传递.Any
给相关模型的方法.
所以我想构建一个谓词:
var castCondition = PredicateBuilder.New<CastInfo>(true);
if (movies != null && movies.Length > 0)
{
castCondition = castCondition.And(c => movies.Contains(c.MovieId));
}
if (roleType > 0)
{
castCondition = castCondition.And(c => c.RoleId == roleType);
}
Run Code Online (Sandbox Code Playgroud)
然后使用它来过滤与谓词中的模型有关的模型:
IQueryable<Name> result = _context.Name.AsExpandable().Where(n => n.CastInfo.Any(castCondition));
return await result.OrderBy(n => n.Name1).Take(25).ToListAsync();
Run Code Online (Sandbox Code Playgroud)
但这导致了 System.NotSupportedException: Could not parse expression 'n.CastInfo.Any(Convert(__castCondition_0, Func``2))': The given arguments did not match the expected arguments: Object of type 'System.Linq.Expressions.UnaryExpression' cannot be converted to type 'System.Linq.Expressions.LambdaExpression'.
我看到类似的问题和答案建议使用.Compile
.或者另外 …
我开始使用LinqKit的PredicateBuilder来创建具有OR条件的谓词,这是Linq表达式无法实现的.
我面临的问题是,如果我开始PredicateBuilder.True<MyEntity>()
它返回所有行,如果我开始PredicateBuilder.False<MyEntity>()
它返回非行,除了我使用的表达式!看下面的代码:
var pre = PredicateBuilder.True<MyEntity>();
pre.And(m => m.IsActive == true);
using (var db = new TestEntities())
{
var list = db.MyEntity.AsExpandable().Where(pre).ToList();
dataGridView1.DataSource = list;
}
Run Code Online (Sandbox Code Playgroud)
它应该返回具有IsActive == true的行,但它返回所有行!
我已经尝试了所有可能的组合PredicateBuilder.True
| PredicateBuilder.False
与And
| Or
方法,不是它们的作品!
在 Entity Framework Core 中使用谓词构建器时出现以下错误。
源 IQueryable 没有实现 IAsyncEnumerable。只有实现 IAsyncEnumerable 的源才能用于实体框架异步操作。
这是代码 -
List<Member> results = await _context.Members.AsExpandable().Where(predicate).ToListAsync();
Run Code Online (Sandbox Code Playgroud)
这是我正在使用的 EF 的确切版本
<package id="EntityFramework.Core" version="7.0.0-rc1-final" targetFramework="net451" />
Run Code Online (Sandbox Code Playgroud) entity-framework predicatebuilder linqkit entity-framework-core
我的 Linq where 子句如何转换为 Sql 时遇到问题。
我正在使用EnumToStringConverter
将我的实体的属性映射enum
到文本数据库列中。当从 DbContext 查询我的实体时,这一切都很好。
然后我开始使用 LinqKit 和 Expressions 来获得可重用的过滤器。我创建了一个表达式,它接受我的实体并作为对实体其他属性的一些计算的结果给出我的枚举。我会尝试用代码来解释自己,因为文字让我失望。我会写一个例子,所以我不必发布完整的代码,但逻辑是一样的。您可以在此处找到带有项目的 GitHub 存储库来复制该问题: https //github.com/pinoy4/efcore-enum-to-string-test
模型类:
public class MyEntity
{
public Guid Id { get; set; }
public MyEnum Status { get; set; }
public DateTime DueAtDate { get; set; }
}
public MyEnum
{
New = 0,
InProgress = 1,
Overdue = 2
}
Run Code Online (Sandbox Code Playgroud)
FluentAPI 配置
public class MyEntityConfiguration : IEntityTypeConfiguration<MyEntity>
{
public void Configure(EntityTypeBuilder<MyEntity> builder)
{
// irrelevant parts of configuration …
Run Code Online (Sandbox Code Playgroud)