如何通过字典筛选子表
如何通过字典筛选子表
我有一个问题要问你们!!!假设我有两个表,一个是父表,另一个是子表。我想通过从子对象发送数据来过滤父表。子表包含4列,如下所示:
{Id, RuleId, RuleKey, RuleValue}
我发送一个字典作为请求,其中包含子对象的2个列(RuleKey,RuleValue)的值。我想返回包含我发送的RuleKey和RuleValue的父对象。
// Key是子表的列名,value是相应的值 var dictionary = new Dictionary() { {"RuleKey", "RuleValue"}, {"RuleKey1", "RuleValue1"} }
这是我尝试的方法,但显然不起作用,仍然会出现语法错误。
关于这个问题有两个问题:
1-) 我应该如何做到这一点(重要的)
2-) 如果我在内存中执行这个操作,会有任何错误吗?如果我记得没错的话,EFCore不会将LINQ转换为SQL脚本,因为内存问题。
var rules = _ruleContext.Rules.AsQueryable(); rules = rules.Where(u => u.Criteria.Where(k => dictionary.Keys.Contains(k.Key) && dictionary.Values.Contains(k.Value)));
public class Rule : Entity{ public string RuleName { get; set; } public string Expression { get; set; } public ICollection Criteria { get; set; } } public class Criteria : Entity { public int RuleId { get; set; } public string Name { get; set; } public string Key { get; set; } public string Operator { get; set; } public string Value { get; set; } public Rule Rule { get; set; } }
如何通过字典过滤子表
问题出现的原因:
用户希望通过使用字典来过滤子表,但不清楚如何实现。
解决方法:
可以使用函数FilterByItems来实现字典过滤子表的功能。下面是具体的解决方法。
首先,创建一个字典对象,其中包含要用于过滤的规则。例如:
var dictionary = new Dictionary() { {"RuleKey", "RuleValue"}, {"RuleKey1", "RuleValue1"} };
然后,使用FilterByItems函数对子表进行过滤。在过滤过程中,使用lambda表达式指定过滤条件。例如:
var matched = _ruleContext.Criterias .FilterByItems(dictionary, (c, kv) => c.Key == kv.Key && c.Value == kv.Value, true) .GroupBy(c => c.RuleId) .Where(g => g.Count() == dictionary.Count) .Select(g => new { RuleId = g.Key, });
接下来,将过滤后的结果与主表进行关联,并选择需要的字段。例如:
var rules = from r in _ruleContext.Rules join m in matched on r.Id equals m.RuleId select r;
最后,将结果转换为数组或其他需要的形式。例如:
var result = rules.ToArray();
通过以上步骤,就可以实现通过字典过滤子表的功能了。
文章结束。
问题的出现原因:
这个问题的出现是因为需要根据字典来过滤子表。根据代码中的描述,需要匹配字典中的键值对,而不是只匹配键或值。目前的代码中,无法实现只匹配键值对的需求。
问题的解决方法:
为了解决这个问题,可以创建一个临时表来存储字典中的键值对,然后使用原始的SQL语句来将子表与临时表进行连接。具体的解决方法如下:
// 为了使用临时表,需要保证连接在表创建语句之后保持打开状态 context.Database.OpenConnection(); try { context.Database.ExecuteSqlRaw("CREATE TABLE #RequiredCriteria ([Value] nvarchar(100), [Key] nvarchar(100))"); // 如果需要处理大量的条件,这可能会成为瓶颈... foreach (var criteria in dictionary) { context.Database.ExecuteSqlInterpolated($"INSERT INTO #RequiredCriteria ([Value], [Key]) VALUES ({criteria.Key}, {criteria.Value})"); } // 这个查询使用原始的SQL语句创建Rule对象,并进行所需的参数连接 var matched = context.Rules.FromSqlRaw( @"SELECT * FROM Rules WHERE Id IN ( SELECT DISTINCT RuleId FROM Criteria C INNER JOIN #RequiredCriteria RC ON C.[Key] = RC.[Key] AND C.[Value] = RC.[Value])") .ToList(); context.Database.ExecuteSqlRaw("DROP TABLE #RequiredCriteria"); } finally { context.Database.CloseConnection(); }
第二个解决方法中添加了一个GROUP BY和HAVING COUNT(RuleId) = {dictionary.Count}的语句,以确保匹配的规则具有与请求的条件相同的不同条件数量。这样,如果请求中重复了相同的条件键和值,也不会造成影响。
如果Criteria表的数据量很大,建议在Key和Value列上建立索引,否则每次查询都会对整个表进行聚集索引扫描。
正确的解决方法是通过原始的SQL语句来实现的。但是可以省略Distinct,因为字典中的键是唯一的。