订单实体框架通过rowversion属性查询,在存储和内存中 [英] Order Entity Framework query by rowversion property, in store and in memory
问题描述
public class Foo
{
[Key]
[MaxLength(50)]
public string FooId {get;组;
[Timestamp]
[ConcurrencyCheck]
public byte [] Version {get;组; }
}
进一步假设我需要获取最近几个这些项目。我可以用一个相当简单的LINQ表达式来实现,它被转换成正确的SQL,并且运行正常。
var recentFoos = db.Foos.OrderBy(f => f.Version).Take(10);
现在,如果这个查询发生在我想要测试的方法中,事情会变得更加复杂。我有一个假的上下文和实体集合的设置,一切都正常。但是,因为 byte []
不能直接排序,尝试执行该代码会抛出一个 ArgumentException
(At至少一个对象必须实现IComparable。)。
另一方面,如果我使用 OrderBy()
它采用比较器,这将在内存中运行,但会抛出异常(...此方法无法转换为存储表达式)尝试针对数据库运行。
有没有办法a)编写一个可以在两种情况下正确运行的LINQ查询,或者b)可靠地检测哪种情况,以便我的代码可以使用正确的重载进行排序? / strong>
我最终实施了解决方案 jnm2建议:写一个 ExpressionVisitor
重写查询从正常查询使用的谓词唯一重载到内存查询所必需的重载。我不得不修改原始Microsoft示例代码为假的 DbSet
允许这些访问者在正确的时刻插入并使用。
一个Gist与我的代码可以在这里找到。如果有人可以提出更优雅的方式来申请访问者,我绝对愿意提供建议。
Assume I have an entity in my (Code First) Entity Framework model that looks like this:
public class Foo
{
[Key]
[MaxLength(50)]
public string FooId { get; set; }
[Timestamp]
[ConcurrencyCheck]
public byte[] Version { get; set; }
}
Assume further that I need to fetch the most recent few of these items. I can do that with a fairly simple LINQ expression, which gets translated into the correct SQL, and runs fine.
var recentFoos = db.Foos.OrderBy(f => f.Version).Take(10);
Now, if that query happens in a method that I also want to test, things get more complicated. I have a setup with fake context and entity collections, and that all works fine. But, because byte[]
can't be sorted directly, trying to execute that code throws an ArgumentException
("At least one object must implement IComparable.").
On the other hand, if I use the overload of OrderBy()
that take a comparer, that will run in memory, but throw an exception ("…this method cannot be translated into a store expression.") trying to run against the database.
Is there a way to either a) write a single LINQ query that will run correctly in both circumstances, or b) to reliably detect which case pertains, so that my code can sort using the correct overload?
I ended up implementing the solution jnm2 suggested: writing an ExpressionVisitor
to rewrite the query from the predicate-only overload used by normal queries to the overload necessary for in-memory querying. I had to rework the original Microsoft sample code for fake DbSet
to allow these visitors to be plugged in and used at the right moment.
A Gist with my code can be found here. If anyone can suggest a more elegant way to apply the visitors, I'm definitely open to suggestions.
这篇关于订单实体框架通过rowversion属性查询,在存储和内存中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!