我正在动态创建LINQ查询,到目前为止我做得很好.
但我被困在我认为不会的地方.在构建该查询的某个点上,我需要访问实体的EnityCollection.像这样的东西:
Expression collection = Expression.Property(entity, typeof(EntityType).GetProperty("CollectionOfRelatedEntities"));
Run Code Online (Sandbox Code Playgroud)
然后,我会在该集合上调用"Where"LINQ方法:
MethodCallExpression AfterWhere = Expression.Call(
typeof(Queryable),
"Where",
new Type[] { typeof(RelatedEntity) },
collection,
Expression.Lambda<Func<RelatedEntity, bool>>(predicate, new ParameterExpression[] { paramOfRelatedEntity }));
Run Code Online (Sandbox Code Playgroud)
通常这会奏效.在这种情况下它不会因为集合是IEnumerable而我需要它是IQueryable以便"Where"工作.
我试过这个:
Expression.Convert(collection, typeof(IQueryable<RelatedEntity>);
Run Code Online (Sandbox Code Playgroud)
但它说无法转换,因为EntityCollection没有实现IQueryable.
我静态地使用AsQueryable来实现我在这里需要的东西,所以我尝试动态地模仿它:
Expression.Call(collection, typeof(EntityCollection<RelatedEntity>).GetMethod("AsQueryable"));
Run Code Online (Sandbox Code Playgroud)
但我得到null引用异常.我无法通过反思达到它.这个AsQueryable方法是扩展方法,它是静态的,在Queryable类中定义,所以我试过:
Expression.Call(collection, typeof(Queryable).GetMethod("AsQueryable", BindingFlags.Static));
Run Code Online (Sandbox Code Playgroud)
相同的结果:"值不能为空".
我在这里达到了极限,我的想法很新鲜.
所以,我问你:
如何动态地将IEnumerable转换为IQueryable?
有没有办法Func<>动态设置类型参数,所以我不必使用无穷无尽的if语句?
就像是:
Type t = Type.GetType("System.Decimal");
Func<t> foo = new Func<t>(some_function);
Run Code Online (Sandbox Code Playgroud)
代替:
Func<Decimal> foo = new Func<Decimal>(some_function);
Run Code Online (Sandbox Code Playgroud)
更新:
这是我代码中的代码段:
Type t = typeof(StavkaDokumenta).GetProperty(pd.Polje).PropertyType;
ParameterExpression pe = Expression.Parameter(typeof(StavkaDokumenta), "stavka");
Expression expr = Expressions.ResolveCompleteExpression(pe, pd.Expression);
Expression final = Expression.Convert(expr, t);
if (t == typeof(decimal))
{
var lambda = Expression.Lambda<Func<StavkaDokumenta, decimal>>(final, pe);
o = lambda.Compile().Invoke(stavka);
}
if (t == typeof(decimal?))
{
var lambda = Expression.Lambda<Func<StavkaDokumenta, decimal?>>(final, pe);
o = lambda.Compile().Invoke(stavka);
}
else if (t == typeof(int))
{
var lambda …Run Code Online (Sandbox Code Playgroud) 我有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方法不是通用的.它虽然是静态的.
有没有办法从其元数据中查看实体的属性是否为导航属性?
我可以通过检查属性是否实现ICollection来确定属性是否是实体集合,从那里我可以断定它是否是导航属性.
但是,如果属性不是实体集合而只是引用另一个实体呢?
SignalR正在工作,而项目是ASP.NET MVC3.现在我将它升级到MVC5(不是那么容易做,我必须告诉你).
然后我注意到signalR没有工作.我按照这本书,将SignalR重新安装到版本2.1.0,安装了OWIN(必须为v2 +)并为项目添加了启动类.
这是我的startup.cs类,它位于项目根文件夹中:
[assembly: OwinStartup(typeof(SISTEM.Startup))]
namespace SISTEM
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我觉得这里没问题,但也许我错过了什么......
现在这里是来自集线器的片段:
namespace SISTEM
{
public class PostingHub : Hub
{
public void Test(string hello)
{
Clients.All.hello(hello);
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后我在视图中引用生成的代理:
<script src="~/Scripts/jquery.signalR-2.1.0.min.js"></script>
<script src="~/signalr/hubs"></script>
Run Code Online (Sandbox Code Playgroud)
我在fiddler中检查它,我可以看到/ signalr/hubs请求正在生成未找到的HTTP 404.
现在,我并不懒惰,我尝试了几件事:
任何帮助,将不胜感激.
更新:来自/ signalr/hubs的响应
<!DOCTYPE html>
<html>
<head>
<title>The resource cannot be found.</title>
<meta name="viewport" content="width=device-width" />
</head>
<body bgcolor="white">
<span><H1>Server …Run Code Online (Sandbox Code Playgroud) 我需要帮助。
实际上,我已经阅读了有关此问题的信息,并且我认为我已经解决了它,但它一直困扰着我。
这是关于开发和生产环境中的不同登录。
这应该是解决方案(EF和SQL Server):
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder((model.Connection as EntityConnection).StoreConnection.ConnectionString);
ConnectionInfo ci = new ConnectionInfo();
ci.ServerName = builder.DataSource;
ci.DatabaseName = builder.InitialCatalog;
ci.UserID = builder.UserID;
ci.Password = builder.Password;
report.SetDatabaseLogon(ci.UserID, ci.Password, builder.DataSource, ci.DatabaseName);
foreach (CrystalDecisions.CrystalReports.Engine.Table tbl in report.Database.Tables)
{
TableLogOnInfo logon = tbl.LogOnInfo;
logon.ConnectionInfo = ci;
tbl.ApplyLogOnInfo(logon);
}
Run Code Online (Sandbox Code Playgroud)
我从实体连接中提取登录信息并将其应用于报表中的所有表。这应该够了吧。我添加 SetDatabaseLogon() 只是为了确定,但这不是必需的。
现在,当我在生产环境中运行报告时,报告会弹出一个数据库登录屏幕,显示正确的服务器名称(生产服务器),数据库旁边没有任何内容(这是我所关心的),正确的用户名,没有密码,要求输入登录信息.
我输入了,但 CR 显示“登录失败。请重试”。我的意思是WTF。我使用相同的凭据通过 Management Studio 连接到数据库。
我正在使用 WPF 查看器,顺便说一句。
我真的被困在这里,我已经做了一些调试,并且连接信息获得了所有正确的数据,所以必须报告谁是罪魁祸首,但我该怎么办?
任何帮助,将不胜感激。我希望有人在我之前偶然发现了同样的问题。
问候
我有一种从数据库获取数据的方法,它是通用的:
public static IQueryable<T> GetData<T>(IQueryable<T> data, some more parameters)
Run Code Online (Sandbox Code Playgroud)
data 是未过滤的数据库实体集合,而 GetData 会对该集合进行过滤、排序、跳过、处理...
当我像平常一样提供 IQueryable 类型的变量(T 是 Document)作为第一个参数时,它当然可以工作:
IQueryable<Document> data = ...
GetData<Document>(data, ....);
Run Code Online (Sandbox Code Playgroud)
现在,我需要动态“计算”第一个参数。为此,我使用 LINQ 表达式,它将计算为 IQueryable,但我不知道编译时是哪个 T。我在想这样的事情:
Expression db = Expression.Constant(new DataModelContainer());
Expression table = Expression.Property(db, tbl); /* tbl = "Documents", this is the whole point */
Type type = table.Type.GetGenericArguments()[0];
Expression call = Expression.Call(typeof(Queryable), "AsQueryable", new Type[] { type }, table);
object o = Expression.Lambda(call, null).Compile().DynamicInvoke();
Run Code Online (Sandbox Code Playgroud)
此时,确实是 IQueryable (IQueryable),因此应该能够作为 GetData 的参数。但是,我只有“对象”引用它,自然不能那样使用它。
所以,我的问题是:当 o 正是这样时,有什么方法可以动态地将 'o' 转换为 'IQueryable' …
我无法阻止任务.首先,我刚开始使用任务.以前,我一直在使用delegate.BeginInvoke()在后台运行,但这次我需要停止后台执行,如果需要的话.所以我切换到了任务.这是我的代码:
CancellationTokenSource token = new CancellationTokenSource();
Task posting = Task.Factory.StartNew(() => DoPosting(docs, session), token.Token);
HttpRuntime.Cache[session.ToString() + "_token"] = token;
HttpRuntime.Cache[session.ToString() + "_task"] = posting;
Run Code Online (Sandbox Code Playgroud)
这是ASP.NET MVC,所以我在HttpRuntime.Cache中存储了持久的东西.用户可以通过此操作取消操作:
public JsonResult StopPosting(string session)
{
CancellationTokenSource token = (CancellationTokenSource)HttpRuntime.Cache.Get(session.ToString() + "_token");
Task posting = (Task)HttpRuntime.Cache[session.ToString() + "_task"];
token.Cancel();
return Json(new { Message = "Stopped!" });
}
Run Code Online (Sandbox Code Playgroud)
现在,当这个动作第一次被击中时,没有任何反应.然后我第二次要求取消.现在,token.IsCancellationRequested说"true",所以token.Cancel()必须做一些事情.但是发布.Status仍然是"正在运行".它会保持这种状态直到它完成,然后它是"RunToCompletion".
所以,我要求取消任务,但它没有被取消.
也许我做错了什么或者我错过了一些明显的东西,但我无法看到/理解为什么它不会取消.
也许有人可以解释一下?
问候.
我需要的是通过 Linq.Expressions 表示此查询:
db.Documents.GroupBy(a => 1).Select(b => b.Sum(c => c.Amount) });
Run Code Online (Sandbox Code Playgroud)
这是我到目前为止所拥有的:
IQueryable<Document> data = db.Documents;
ParameterExpression pe = Expression.Parameter(typeof(Document), "doc");
Expression groupBy = Expression.Call(
typeof(Queryable),
"GroupBy",
new Type[] { typeof(Document), typeof(int) },
data.Expression,
Expression.Lambda(Expression.Constant(1), pe));
ParameterExpression peg = Expression.Parameter(typeof(IGrouping<int, Document>), "group");
Expression select = Expression.Call(
typeof(Queryable),
"Select",
new Type[] { typeof(IGrouping<int, Document>), typeof(int) },
groupBy,
Expression.Lambda(Expression.Property(peg, "Key"), peg));
foreach (var item in data.Provider.CreateQuery(select)) { ... }
Run Code Online (Sandbox Code Playgroud)
这是执行:
db.Documents.GroupBy(a => 1).Select(b => b.Key });
Run Code Online (Sandbox Code Playgroud)
而且效果很好。现在,我想聚合一个总和,而不是访问组的密钥。
这对我来说是棘手的地方。我在想这样的事情:
ParameterExpression pe1 = Expression.Parameter(typeof(Document), …Run Code Online (Sandbox Code Playgroud) 我是新来的...
我有一个问题,如果有人可以帮助我.
它是关于计时器(System.Threading.Timer).
我想打破不可避免的递归:我在datarow中有两列,它们是相互依赖的(price_without_VAT和price_with_VAT).设置其中一个肯定会导致StackOverflowException.所以这就是这个想法:
bool flag = true;
void Reset(object state) { flag = true; }
Run Code Online (Sandbox Code Playgroud)
现在,包装用于更改其中一列的值的方法:
{
if(flag)
{
flag = false;
System.Threading.Timer tmr = new System.Threading.Timer(new System.Threading.TimerCallback(Reset), null, 10, System.Threading.Timeout.Infinite);
datarow.other_column = value;
}
}
Run Code Online (Sandbox Code Playgroud)
datarow.other_column.value行将立即触发上述方法,但不会有递归,因为flag为false.在10毫秒标志应该回到真,一切都恢复正常.
现在,当我按照DEBUGGER中的代码进行操作时,一切正常,但是当我启动应用程序NORMALLY重置功能根本不会触发,标志永远停留在虚假状态,并且一切都是假的.我玩弄due_time参数但似乎没有任何帮助.
有任何想法吗?
c# ×9
linq ×4
expression ×2
asp.net-mvc ×1
casting ×1
count ×1
dynamic ×1
func ×1
iqueryable ×1
lambda ×1
properties ×1
proxy ×1
signalr ×1
sql-server ×1
task ×1
timer ×1
types ×1