使用Linq按属性名称和值匹配对象
本文关键字:对象 Linq 属性 使用 | 更新日期: 2023-09-27 18:16:39
我需要能够通过使用单个Linq查询匹配属性名称和值来匹配对象到记录。我不明白为什么这是不可能的,但我一直没能想出如何让它工作。现在我可以用循环来做,但是这个很慢。
场景如下:
我已经建立了一些表,通过将它们的主键放入具有键的属性名称和值的关联表中来存储任何给定实体的记录。
如果我在运行时有一个随机对象,我需要能够检查数据库中是否存在该对象的副本,方法是检查对象的属性名是否与数据库中记录的所有键匹配(这意味着它们将是相同类型的对象),然后检查每个键的值是否匹配,给我相同的记录。
下面是我如何使用循环(简化了一点)让它工作的:
public IQueryable<ResultDataType> MatchingRecordFor(object entity)
{
var result = Enumerable.Empty<ResultDataType>();
var records = _context.DataBaseRecords
var entityType = entity.GetType();
var properties = entityType.GetProperties().Where(p => p.PropertyType.Namespace == "System");
foreach (var property in properties)
{
var name = property.Name;
var value = property.GetValue(entity);
if (value != null)
{
var matchingRecords = records.Where(c => c.DataBaseRecordKeys.Any(k => k.DataBaseRecordKeyName == name && k.DataBaseRecordValue == value.ToString()));
if (matchingRecords.Count() > 0)
{
records = matchingRecords;
}
}
}
result = (from c in records
from p in c.DataBaseRecordProperties
select new ResultDataType()
{
ResultDataTypeId = c.ResultDataTypeID,
SubmitDate = c.SubmitDate,
SubmitUserId = c.SubmitUserId,
PropertyName = p.PropertyName
});
return result.AsQueryable();
}
最后一条语句用所有属性的信息连接一个与数据库记录相关的属性表。
这对于单个记录来说工作得很好,但是我想要摆脱这个循环,这样我就可以加快速度来处理许多记录。
using System.Reflection;
public IQueryable<ResultDataType> MatchingRecordFor(object entity)
{
var records = _context.DataBaseRecords;
var entityType = entity.GetType();
var properties = entityType.GetProperties().Where(p => p.PropertyType.Namespace == "System");
Func<KeyType, PropertyInfo, bool> keyMatchesProperty =
(k, p) => p.Name == k.DataBaseRecordKeyName && p.GetValue(entity).ToString() == k.DataBaseRecordValue;
var result =
from r in records
where r.DataBaseRecordKeys.All(k => properties.Any(pr => keyMatchesProperty(k, pr)))
from p in r.DataBaseRecordProperties
select new ResultDataType()
{
ResultDataTypeId = r.ResultDataTypeId,
SubmitDate = r.SubmitDate,
SubmitUserId = r.SubmitUserId,
PropertyName = p.PropertyName
});
return result.AsQueryable();
}
希望我的查询语言是正确的。你必须对它进行基准测试,看看它是否比你原来的方法更有效。
编辑:这是错误的,见注释