使用Linq按属性名称和值匹配对象

时间:2014-08-05 22:04:42

标签: c# linq entity-framework key-value

我需要能够通过使用单个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();
}

最后一个语句将与数据库记录相关的属性表与所有属性的信息相连接。

这对于单个记录来说效果很好,但我想摆脱这个循环,这样我就可以加快速度,从而可以处理许多记录。

1 个答案:

答案 0 :(得分:0)

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();
}

希望我能正确使用该查询语言。您必须对其进行基准测试,看它是否比您原来的方法更有效。

编辑:这是错误的,请参阅评论