假设我有一个IQueryable<T>表达式,我想封装它的定义,存储它并重用它,或者稍后将它嵌入到更大的查询中.例如:
IQueryable<Foo> myQuery =
from foo in blah.Foos
where foo.Bar == bar
select foo;
Run Code Online (Sandbox Code Playgroud)
现在我相信我可以保持myQuery对象并像我描述的那样使用它.但有些事情我不确定:
如何最好地参数化?最初我在一个方法中定义了这个,然后IQueryable<T>作为方法的结果返回.这样我就可以定义blah和bar作为方法参数,我猜它IQueryable<T>每次都会创建一个新的.这是封装逻辑的最佳方法IQueryable<T>吗?还有其他方法吗?
如果我的查询解析为标量而不是IQueryable? 例如,如果我希望此查询完全如所示,但附加.Any()只是让我知道是否有任何匹配的结果?如果我添加,(...).Any()则结果bool立即执行,对吧?有没有使用这些方式Queryable运营(Any,SindleOrDefault,等),但不立即执行?LINQ-to-SQL如何处理这个问题?
编辑:第2部分更多的是试图了解IQueryable<T>.Where(Expression<Func<T, bool>>)vs. 之间的限制差异IQueryable<T>.Any(Expression<Func<T, bool>>).在创建要延迟执行的大型查询时,似乎后者并不灵活.的Where()可以追加,然后在其它构建体可以稍后所附,然后最终执行.由于Any()返回标量值,因此它可以在构建其余查询之前立即执行.
我有IQueryable对象,我需要将IQueryable中的数据放入Textboxs控件中.这可能吗?
我试着像:
public void setdata (IQueryable mydata)
{
textbox1.text = mydata.????
}
Run Code Online (Sandbox Code Playgroud)
我这样做:
public IQueryable getData(String tableName, Hashtable myparams)
{
decimal id = 0;
if (myparams.ContainsKey("id") == true)
id = (decimal)myparams["id"];
Type myType= Type.GetType("ORM_Linq." + tableName + ", ORM_Linq");
return this.GetTable(tableName , "select * from Articu where id_tipo_p = '" + id + "'");
}
public IQueryable<T> GetTable<T>(System.Linq.Expressions.Expression<Func<T, bool>> predicate) where T : class
{
return _datacontext.GetTable<T>().Where(predicate);
}
Run Code Online (Sandbox Code Playgroud)
这将返回{System.Data.Linq.SqlClient.SqlProvider+OneTimeEnumerable1 [ORM_Linq.Articu]}`
我没有看到你告诉我的任何方法.我看到Cast <>,Expression,ToString ......
有人可以指出为什么会发生这种情况:
我正在使用它NHibernate和Linq它的提供者.
此处列出了失败的代码:
var sequence = session.Query<T>();
var wtfSequence = sequence.Where(x => true);
var okaySequence = sequence.Where(x => x.Id > 0);
Run Code Online (Sandbox Code Playgroud)
调试显示sequence(IQueryable<T>之后)包含2个元素,这些元素已添加到数据库中.
我希望第一个Where语句产生该序列中的所有元素,但不幸的是它留下了0个元素.
Where相反,第二个陈述实际上产生了2个元素,因为它应该起作用.
以下是NHibernate -> Sqlite第一个和第二个Where语句的查询.
NHibernate: select cast(count(*) as INTEGER) as col_0_0_ from "BinaryUnitProxy_IndicatorUnitDescriptor" binaryunit0_ where @p0='true';@p0 = 'True' [Type: String (0)]
NHibernate: select cast(count(*) as INTEGER) as col_0_0_ from "BinaryUnitProxy_IndicatorUnitDescriptor" binaryunit0_ where binaryunit0_.Id>@p0;@p0 = 0 [Type: Int32 (0)]
Run Code Online (Sandbox Code Playgroud)
现在,如果我用my测试相同的代码InMemoryRepository,它将每个实体存储在一个简单的列表中,那么这个 …
我有IQueryable <T>源,我想动态调用IQueryable <T> .Count().
所以,我需要在IQueryable中声明的Count方法的MethodInfo.
这是来自msdn的签名(在IQueryable <>中):
public static int Count<TSource>(
this IQueryable<TSource> source
)
Run Code Online (Sandbox Code Playgroud)
这是我有多远:
Expression expr; //this is expression which holds my IQueryable<T>
MethodInfo mi = expr.Type.GetMethod("Count", BindingFlags.Static | BindingFlags.Public, null, new[] { expr.Type }, null);
Run Code Online (Sandbox Code Playgroud)
但我的mi总是空的;
我也尝试过:
mi = typeof(IQueryable<>).GetMethod("Count", BindingFlags.Static | BindingFlags.Public, null, new[] { expr.Type }, null);
Run Code Online (Sandbox Code Playgroud)
但又是空的.
我的最终目标是:
Expression.Call(mi, expr);
Run Code Online (Sandbox Code Playgroud)
更新:这是我得到Sum Extension方法的方法:
MethodInfo sum = typeof(Queryable).GetMethod("Sum", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(IQueryable<decimal>) }, null);
Run Code Online (Sandbox Code Playgroud)
这是有效的,但这个Sum方法不是通用的.它虽然是静态的.
我在我的存储库中有这个,它按预期工作:
public virtual EntityClass GetById(int id)
{
return db.Set<EntityClass>().Find(id);
}
Run Code Online (Sandbox Code Playgroud)
但是,我有一些表有太多的列(例如:10列,我只需要3个)或一些表,我在那里有长文本,再次,他们不需要被提取.
我在想是否有办法仍然可以通过主键搜索但可能获得IQueryable结果?或者至少可以让我做这样的事情:
var blah = myRepo.GetById(myId).Select(s => new {column 2, column 3, column 7})
Run Code Online (Sandbox Code Playgroud) 我正在构建一个类型的表达式,Expression<Func<Project, bool>>它IQueryable<Project>从数据库返回正确的.IQueryable<Project>有一个SubProjects我想要过滤的嵌套集合.它看起来像这样
这可以通过一次调用数据库完成吗?
例如:
Expression<Func<Project, bool>> projectFilter = FilterEnabled();
projectFilter = projectFilter.And(GetProjectsByOrganization());
var projectData = GetProjectsAsQueryable(projectFilter); //returns correct projects
Run Code Online (Sandbox Code Playgroud)
这就是我想做的事情:
Expression<Func<Project, bool>> projectFilter = FilterEnabled();
projectFilter = projectFilter.And(GetProjectsByOrganization())
.And(GetSubProjectsByStartDate());
var projectData = GetProjectsAsQueryable(projectFilter); //returns correct projects and the filtered sub projects by start date
Run Code Online (Sandbox Code Playgroud)
的GetProjectsByOrganization是如下
public Expression<Func<Project, bool>> GetProjectByOrganization()
{
var organizationIDs = new List<Guid>();
if (FilterCriteria.OrganiazaitonId != null)
organizationIDs = OrganizationRepository.GetParentAndChildrenOrganizationIds(FilterCriteria.OrganiazaitonId.Value).ToList();
//...
return prj => FilterCriteria.OrganiazaitonId == null || …Run Code Online (Sandbox Code Playgroud) 根据NHProf,不鼓励使用隐式交易:
http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions
但是,NHibernate LINQ IQueryable<>在从数据库中读取对象时返回一个,这是懒惰的评估.我在存储库中有这个方法:
public IQueryable<T> GetAll<T>()
{
using (var transaction = _session.BeginTransaction())
{
var data = _session.Linq<T>();
transaction.Commit();
return data;
}
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是该方法将在data评估之前提交事务.有没有办法使用存储库模式并保持IQueryable<>显式事务?或者读取操作是否可以使用隐式事务?
在使用真实数据库之前构建一个应用程序,只是为了让事情有效我可以先使用硬编码列表作为虚假的内存存储库:
public class FakeProductsRepository
{
private static IQueryable<Product> fakeProducts = new List<Product> {
new Product{ ProductID = "xxx", Description = "xxx", Price = 1000},
new Product{ ProductID = "yyy", Description = "xxx", Price = 2000},
new Product{ ProductID = "zzz", Description = "xxx", Price = 3000}
}.AsQueryable();
public IQueryable<Product> Products
{
get { return fakeProducts; }
}
}
Run Code Online (Sandbox Code Playgroud)
如何向此类添加方法以动态地在此列表中添加新的,而不是硬编码的项目?
我正在尝试为我的EF存储库实现一个缓存方案,类似于此处的博客.正如作者和评论者所报告的那样,限制是密钥生成方法无法生成随给定查询的参数而变化的缓存键.这是缓存密钥生成方法:
private static string GetKey<T>(IQueryable<T> query)
{
string key = string.Concat(query.ToString(), "\n\r",
typeof(T).AssemblyQualifiedName);
return key;
}
Run Code Online (Sandbox Code Playgroud)
因此,以下查询将生成相同的缓存键:
var isActive = true;
var query = context.Products
.OrderBy(one => one.ProductNumber)
.Where(one => one.IsActive == isActive).AsCacheable();
Run Code Online (Sandbox Code Playgroud)
和
var isActive = false;
var query = context.Products
.OrderBy(one => one.ProductNumber)
.Where(one => one.IsActive == isActive).AsCacheable();
Run Code Online (Sandbox Code Playgroud)
请注意,唯一的区别在于isActive = true第一个查询和isActive = false第二个查询.
任何有效生成因IQueryable参数而异的缓存键的建议/见解都将得到真正的体会.
感谢Sergey Barskiy分享EF CodeFirst缓存方案.
我采用了遍历IQueryable表达式树的方法,目的是解析查询中使用的参数值.根据maxlego的建议,我扩展了System.Linq.Expressions.ExpressionVisitor类来访问我们感兴趣的表达式节点 - 在本例中是MemberExpression.更新的GetKey方法如下所示:
public …Run Code Online (Sandbox Code Playgroud) caching entity-framework iqueryable repository ef-code-first
有可能以Predicate<T> to Expression<Func<T, bool>>某种方式转换?
我想使用我的ICollectionView的过滤器使用下一个IQueryable函数:
public static System.Linq.IQueryable<TSource> Where<TSource>(this System.Linq.IQueryable<TSource> source, System.Linq.Expressions.Expression<System.Func<TSource, bool>> predicate)
Run Code Online (Sandbox Code Playgroud)
谢谢
iqueryable ×10
c# ×8
linq ×7
nhibernate ×2
caching ×1
count ×1
expression ×1
lambda ×1
list ×1
predicate ×1
repository ×1
transactions ×1