如何在没有泛型类型的情况下进行查询?
我将从一段代码开始:
var objectType = typeof(Department); // Department is entity class from linqdatacontext
using (var dataContext = new DataModel.ModelDataContext())
{
var entity = Expression.Parameter(objectType, "model");
var keyValue = Expression.Property(entity, "Id");
var pkValue = Expression.Constant(reader.Value);
var cond = Expression.Equal(keyValue, pkValue);
var table = dataContext.GetTable(objectType);
... // and here i don't how to proceed
}
我什至不确定我是否正确构建了该表达式。但简单地说,我需要在该表上动态调用 SingleOrDefault()
以通过主键查找实体。我发现的每个示例都使用 GetTable<>()
的通用变体,但我显然无法使用它。我可能忽略了一些东西......
I'll start with piece of code:
var objectType = typeof(Department); // Department is entity class from linqdatacontext
using (var dataContext = new DataModel.ModelDataContext())
{
var entity = Expression.Parameter(objectType, "model");
var keyValue = Expression.Property(entity, "Id");
var pkValue = Expression.Constant(reader.Value);
var cond = Expression.Equal(keyValue, pkValue);
var table = dataContext.GetTable(objectType);
... // and here i don't how to proceed
}
I am not even sure if i am building that expression correctly. However simply put, i need to call dynamically SingleOrDefault()
on that table to find entity by primary key. Every example i had found is using generic variant of GetTable<>()
, but i cannot use that obviously. I am probably overlooking something...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
每当我构建表达式树时,我喜欢从我正在构建的示例开始:
从中,我们可以轻松地剖析目标表达式。你已经走到一半了;您只需要在表达式树中包含对
GetTable
方法的调用,然后构建外部 lambda 表达式来调用整个事物:我们必须将
SingleOrDefault
调用转换为具有对象的返回类型,因此它可以用作Func
(未经测试)
编辑:参数化数据上下文和值
现在我们正在构建此函数:
您可以将常量更改为参数并将这些参数添加到您编译的函数中:
Whenever I build expression trees, I like to start off with an example of what I'm building:
From that, we can easily dissect the target expression. You are partway there; you just need to include a call to the
GetTable
method in the expression tree and then build an outer lambda expression to call the whole thing:We have to convert the
SingleOrDefault
call to have a return type of object so it can serve as the body of theFunc<object>
function.(Untested)
Edit: Parameterizing the data context and value
Now we are building this function:
You would change the constants to parameters and add those parameters to the function you compile:
如果您使用的是 .NET 4,您可以尝试将返回的对象转换为
动态
,这样您就可以像这样进行查询。If you are using .NET 4, you could try casting your returned objects as
dynamic
, so you could then query like this.我仍然不完全确定你的整个问题(我怀疑关于
dynamic
的答案也将解决部分问题)。不过,还是简单回答一下:对于任何
T
、Table
实现(以及其他接口) )ITable
和ITable
。前者是通用类型的,后者不是。表单
GetTable()
返回这样一个Table
。但是,GetTable(Type t)
表单返回一个ITable
。由于ITable
继承自IQueryable
,因此您可以查询它。如果您需要对该查询执行某些通常需要了解类型的操作(例如比较给定的属性),那么根据 Steve Danner 之前给出的答案,dynamic
允许这种情况发生。I'm still not entirely sure as to the whole of your problem (and I suspect the answer about
dynamic
is going to solve part of what will come up too). Still, just to answer:For any
T
,Table<T>
implements (among other interfaces)ITable<T>
andITable
. The former is generically typed, the latter not.The form
GetTable<T>()
returns such aTable<T>
. However, the formGetTable(Type t)
returns anITable
. SinceITable
inherits fromIQueryable
you can query it. If you need to do something with that query that would normally require knowledge of the type (such as comparing on a given property) thendynamic
as per the previous answer given by Steve Danner allows that to happen.我会使用反射和 LINQ 动态查询库,个人认为。
您可以使用 dataContext.Mapping.GetMetaType(objectType).IdentityMembers 获取表的所有键的列表,然后使用 dataContext.GetTable(objectType) 的方式访问数据.Where(key.Name + "==@0", id).
显然,我在那里遗漏了几个步骤 - 如果您有多个键,则需要通过
.IdentityMembers
循环构建一个更完整的谓词,并且如果您总是只有一个键,您可以在其上使用 .First() 。我也没有测试过,但应该非常接近。总共可能有 6-7 行代码 - 如果您需要,我可以将其编写(并测试)。编辑:可以从 Microsoft 下载 LINQ 动态查询库,网址为 http://msdn。 microsoft.com/en-us/vcsharp/bb894665.aspx - 只需将 DynamicLINQ.cs 包含在您的项目中即可。
I'd do it using Reflection and the LINQ dynamic query library, personally.
You can get the list of all the keys for a table with
dataContext.Mapping.GetMetaType(objectType).IdentityMembers
, then access the data with something along the lines ofdataContext.GetTable(objectType).Where(key.Name + "==@0", id)
.Obviously, I left out a few steps in there - if you have multiple keys, you'll need to build a fuller predicate with a loop over
.IdentityMembers
, and if you always just have the one key, you can use .First() on it. I haven't tested it either, but it should be pretty close. It'd probably be 6-7 lines of code total - I can write it up (and test) if you need it.Edit: The LINQ Dynamic Query Library can be downloaded from Microsoft at http://msdn.microsoft.com/en-us/vcsharp/bb894665.aspx - just include DynamicLINQ.cs in your project and you're good.