c# - LINQ 查询将两个表连接在一起以返回错误的值
问题描述
我有一个 linq 查询,它通过匹配方法名称将两个表连接在一起。在表中,我需要查找“全局”值,如果找到,则将称为“参数”的方法中的子元素相互比较,以确保两个表具有相同的对应项,并且如果一个方法参数与其他任何一个参数不匹配然后返回假。
下面是一个结果示例。我们可以看到 seqEquals 找到了一个不等于任何其他方法的“方法”,但是,LINQ 查询返回所有值,我想只提取“seqEquals”的假我尝试将字符串比较放在其中'where' 子句,但是结果并没有像预期的那样相互比较。
{ mOneName = GetItemsJSON, seqEqual = False, mOneParm = [
{
"name": "itemTypes",
"type": "List"
},
{
"name": "textSearch",
"type": "String"
}
], mTwoParm = [
{
"name": "propertyId",
"type": "String"
},
{
"name": "revClassIds",
"type": "List"
},
{
"name": "itemTypes",
"type": "List"
},
{
"name": "textSearch",
"type": "String"
},
{
"name": "eventId",
"type": "String"
}
] }
C# 代码
var ST1 = firstOrgST["records"][0]["SymbolTable"]["methods"];
var ST2 = secondOrgST["records"][0]["SymbolTable"]["methods"];
// joins both tables and pulls the methods containing global from the joins
var STDiff =
from one in ST1
join two in ST2
on one.Value<String>("name") equals two.Value<string>("name")
where one["modifiers"].Values().Contains("global")
select new
{
mOneName = one["name"],
seqEqual = one["parameters"].ToString() == two["parameters"].ToString(),
mOneParm = one["parameters"],
mTwoParm = two["parameters"]
};
var errorFound = false;
var errorMethod = "";
foreach (var i in STDiff)
{ Console.WriteLine(i);
if (!i.seqEqual)
{
errorFound = true;
errorMethod = i.mOneName.ToString();
break;
}
}
// if error is found prints to console the class name as well as the method name
if (errorFound)
{
Console.WriteLine(Path.GetFileNameWithoutExtension(symbolTable) + " on method: " + errorMethod + " has different parameters.\n");
isDifferent = true;
}
数据示例:这是表一。表二可能有不同的参数
{
"SymbolTable": {
"methods": [
{
"annotations": [
{
"name": "TestVisible"
}
],
"location": {
"column": 20,
"line": 1056
},
"modifiers": [
"private"
],
"name": "GetItemsJSON",
"parameters": [
{
"name": "propertyId",
"type": "String"
},
{
"name": "revClassIds",
"type": "List"
},
{
"name": "itemTypes",
"type": "List"
},
{
"name": "itemCategories",
"type": "List"
},
{
"name": "textSearch",
"type": "String"
},
{
"name": "eventId",
"type": "String"
}
],
"references": [],
"returnType": "String",
"type": null
},
{
"annotations": [],
"location": {
"column": 26,
"line": 4313
},
"modifiers": [
"static",
"global"
],
"name": "GetItemsJSON",
"parameters": [
{
"name": "itemTypes",
"type": "List"
},
{
"name": "textSearch",
"type": "String"
}
],
"references": [],
"returnType": "String",
"type": null
},
{
"annotations": [],
"location": {
"column": 26,
"line": 4316
},
"modifiers": [
"static",
"global"
],
"name": "GetItemsJSON",
"parameters": [
{
"name": "propertyId",
"type": "String"
},
{
"name": "revClassIds",
"type": "List"
},
{
"name": "itemTypes",
"type": "List"
},
{
"name": "textSearch",
"type": "String"
},
{
"name": "eventId",
"type": "String"
}
]
}
]
}
}
解决方案
我建议您将数据表转换为对象列表,然后运行您的 linq 查询。
1)使用这样的通用方法将 DataTable 转换为对象列表
private static List<T> ConvertDataTable<T>(DataTable dt)
{
List<T> data = new List<T>();
foreach (DataRow row in dt.Rows)
{
T item = GetItem<T>(row);
data.Add(item);
}
return data;
}
private static T GetItem<T>(DataRow dr)
{
Type temp = typeof(T);
T obj = Activator.CreateInstance<T>();
foreach (DataColumn column in dr.Table.Columns)
{
foreach (PropertyInfo pro in temp.GetProperties())
{
if (pro.Name == column.ColumnName)
pro.SetValue(obj, dr[column.ColumnName], null);
else
continue;
}
}
return obj;
}
2) 在对象列表上使用这样的 Linq 查询
var ST1 = myTableData.ToList();
var ST2 = myTableData.ToList();
var STDiff = from one in ST1
join two in ST2
on one.name equals two.name
where one.modifiers.Contains("global")
select new
{
mOneName = one.name,
seqEqual = CompareParamsAndGetMatchingIndex(one.parameters, two.parameters),
mOneParm = one.parameters,
mTwoParm = two.parameters
};
private int CompareParamsAndGetMatchingIndex(Parameter[] items1, Parameter[] items2)
{
if (items1.Length > items2.Length)
{
return items2.Select((Parameter p, int i) => p.Equals(items1[i]) ? 1 : 0).Sum();
}
else
{
return items1.Select((Parameter p, int i) => p.Equals(items2[i]) ? 1 : 0).Sum();
}
}
public class SymbolTableRoot
{
public Symboltable SymbolTable { get; set; }
}
public class Symboltable
{
public Method[] methods { get; set; }
}
public class Method
{
public Annotation[] annotations { get; set; }
public Location location { get; set; }
public string[] modifiers { get; set; }
public string name { get; set; }
public Parameter[] parameters { get; set; }
public object[] references { get; set; }
public string returnType { get; set; }
public object type { get; set; }
}
public class Location
{
public int column { get; set; }
public int line { get; set; }
}
public class Annotation
{
public string name { get; set; }
}
public class Parameter : IEquatable<Parameter>
{
public string name { get; set; }
public string type { get; set; }
public bool Equals(Parameter other)
{
return other?.name == name && other?.type == type;
}
}
推荐阅读
- reactjs - 如何取消链接已删除的全局包?
- mpi - 在 MPI 下运行时使用非线性求解器时优化挂起
- windows - 如果它们在 Windows 命令提示符中具有相同的名称,有什么方法可以指定两个命令之一?
- nginx - 无法更改 ngx_pagespeed 的选项
- javascript - document.ready 时绘制数据表
- c - 我想使用给定的功能代码按升序打印它们
- request - 如何使用 Fiddler 模拟“没有任何数据的服务器关闭连接”?
- database - System.Data.SqlClient.SqlException:'关键字'order'附近的语法不正确。'
- python - 为什么我的媒体库中的图像没有显示在我的主页中?
- angular - 单击外部时如何阻止角垫菜单关闭?