gpt4 book ai didi

c# - 如何在 LINQ 中动态创建连接?

转载 作者:行者123 更新时间:2023-11-30 22:11:16 24 4
gpt4 key购买 nike

我正在尝试在 LINQ 中动态创建联接。 This answer让我清楚地知道从哪里开始。但是,当“foreing key”是 int? 时,我遇到了一个问题 (int 有效)。当它是一个 int? 时,它会触发一个异常。

我制作了一个简单的 LINQ to Objects 示例来说明问题。为了运行我的示例,您需要 install the dynamic linq Nuget package因为我将它用于 DynamicExpression.ParseLambda 方法。

这是触发异常的代码:

public class Contact
{
public int Id { get; set; }

public string Name { get; set; }
}

public class Address
{
public int Id { get; set; }
public int? ContactId { get; set; }

public string Zip { get; set; }
}

class Program
{
static void Main(string[] args)
{
var contacts = new List<Contact>();
var addresses = new List<Address>();

LambdaExpression outerSelectorLambda = DynamicExpression.ParseLambda(typeof(Contact), null, "Id", new object[0]);
LambdaExpression innerSelectorLambda = DynamicExpression.ParseLambda(typeof(Address), null, "ContactId", new object[0]);
ParameterExpression[] parameters = new ParameterExpression[] { Expression.Parameter(typeof(Contact), "outer"), Expression.Parameter(typeof(Address), "inner") };
LambdaExpression resultsSelectorLambda = DynamicExpression.ParseLambda(parameters, null, "outer.Id", new object[0]);

// BLOWS UP HERE
var queryExpression = Expression.Call(
typeof(Queryable), "Join",
new Type[] { typeof(Contact), typeof(Address), typeof(int?), typeof(int) },
contacts.AsQueryable().Expression, addresses.AsQueryable().Expression,
Expression.Quote(outerSelectorLambda), Expression.Quote(innerSelectorLambda), Expression.Quote(resultsSelectorLambda));

// it will not reach the following line
var queryable = contacts.AsQueryable().Provider.CreateQuery(queryExpression);
}
}

要使上述代码有效,只需将出现的两次 int? 替换为 int。一切都会好起来的。问题在于 Address.ContactIdint?

问题是:为什么会发生这种情况,我该如何解决?

异常信息(葡萄牙语):

System.InvalidOperationException was unhandled
HResult=-2146233079
Message=Nenhum método genérico 'Join' no tipo 'System.Linq.Queryable' é compatível com os argumentos e os argumentos de tipo fornecidos. Nenhum argumento de tipo deve ser fornecido se o método for não genérico.
Source=System.Core
StackTrace:
em System.Linq.Expressions.Expression.FindMethod(Type type, String methodName, Type[] typeArgs, Expression[] args, BindingFlags flags)
em System.Linq.Expressions.Expression.Call(Type type, String methodName, Type[] typeArguments, Expression[] arguments)
em problems.Program.Main(String[] args) na d:\POCs\problems\problems\Program.cs:linha 38
em System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
em System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
em Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
em System.Threading.ThreadHelper.ThreadStart_Context(Object state)
em System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
em System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
em System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
em System.Threading.ThreadHelper.ThreadStart()
InnerException:

最佳答案

问题是你的 key 类型是int? ,但是 ParseLambda您用来创建键选择器的方法是创建类型为 Expression<Func<Contact, int>> 的表达式为您的外键选择器。它没有将结果映射到可为空的 int。该函数与 Join 的签名不兼容。方法,所以它会抛出异常。

如果为了您的示例,您对选择器使用以下表达式,它将正常工作:

Expression<Func<Contact, int?>> outerSelectorLambda = c => c.Id;

查看 ParseLambda 的 API ,您应该使用第二个参数来指定 lambda 的返回类型,所以不要保留它 null :

DynamicExpression.ParseLambda(typeof(Contact), typeof(int?),
"Id", new object[0]);

关于c# - 如何在 LINQ 中动态创建连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20335245/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com