< Summary - Combined Code Coverage

Information
Class: NLightning.Infrastructure.Repositories.Database.Helpers.PrimaryKeyHelper
Assembly: NLightning.Infrastructure.Repositories
File(s): /home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure.Repositories/Database/Helpers/PrimaryKeyHelper.cs
Tag: 36_15743069263
Line coverage
0%
Covered lines: 0
Uncovered lines: 58
Coverable lines: 58
Total lines: 89
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 30
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetPrimaryKeyExpression(...)0%930300%
GetPrimaryKeyExpression(...)0%930300%

File(s)

/home/runner/work/nlightning/nlightning/src/NLightning.Infrastructure.Repositories/Database/Helpers/PrimaryKeyHelper.cs

#LineLine coverage
 1using System.Linq.Expressions;
 2using System.Runtime.CompilerServices;
 3
 4namespace NLightning.Infrastructure.Repositories.Database.Helpers;
 5
 6using Persistence.Contexts;
 7
 8public static class PrimaryKeyHelper
 9{
 10    public static Expression<Func<TEntity, bool>>? GetPrimaryKeyExpression<TEntity>(object id, NLightningDbContext conte
 11        where TEntity : class
 012    {
 013        var keyProperties = context.Model.FindEntityType(typeof(TEntity))?.FindPrimaryKey()?.Properties
 014            ?? throw new InvalidOperationException("Entity does not have a primary key defined.");
 15
 16        object[] keyValuesToUse;
 17
 018        if (keyProperties.Count > 1) // We're dealing with composite keys
 019        {
 020            if (id is not ITuple idTuple)
 021                throw new ArgumentException($"The provided id must be a tuple with {keyProperties.Count} items " +
 022                                            $"for entity {typeof(TEntity).Name}.", nameof(id));
 23
 024            if (idTuple.Length != keyProperties.Count)
 025                throw new ArgumentException($"The number of items in the provided tuple ({idTuple.Length}) does not" +
 026                                            $" match the number of primary key properties ({keyProperties.Count}) " +
 027                                            $"for entity {typeof(TEntity).Name}.", nameof(id));
 28
 029            keyValuesToUse = new object[keyProperties.Count];
 030            for (var i = 0; i < keyProperties.Count; i++)
 031            {
 032                var value = idTuple[i];
 33
 034                keyValuesToUse[i] = value ?? throw new ArgumentNullException(
 035                    nameof(id), $"Item {i} in the provided tuple cannot be null.");
 036            }
 037        }
 38        else // We're dealing with a single key
 039        {
 040            if (id is ITuple)
 041                throw new ArgumentException($"The provided id must not be a tuple for entity {typeof(TEntity).Name}.",
 042                                            nameof(id));
 43
 044            keyValuesToUse =
 045            [
 046                id ?? throw new ArgumentNullException(nameof(id), "The provided id cannot be null.")
 047            ];
 048        }
 49
 050        var parameter = Expression.Parameter(typeof(TEntity), "e");
 051        Expression? predicateBody = null;
 52
 053        for (var i = 0; i < keyProperties.Count; i++)
 054        {
 055            var keyProperty = keyProperties[i];
 056            var keyValue = keyValuesToUse[i];
 57            object? correctlyTypedKeyValue;
 58
 059            var propertyClrType = keyProperty.ClrType;
 060            if (keyValue.GetType() != propertyClrType)
 061            {
 62                try
 063                {
 064                    var underlyingType = Nullable.GetUnderlyingType(propertyClrType);
 065                    correctlyTypedKeyValue = Convert.ChangeType(keyValue, underlyingType ?? propertyClrType);
 066                }
 067                catch (Exception ex)
 068                {
 069                    throw new ArgumentException(
 070                        $"Key value '{keyValue}' (type: {keyValue.GetType().Name}) for property '{keyProperty.Name}' " +
 071                        $"could not be converted to the expected type '{propertyClrType.Name}'.", ex);
 72                }
 073            }
 74            else
 075            {
 076                correctlyTypedKeyValue = keyValue;
 077            }
 78
 079            var memberAccess = Expression.Property(parameter, keyProperty.Name);
 080            var constantValue = Expression.Constant(correctlyTypedKeyValue, propertyClrType);
 081            var equality = Expression.Equal(memberAccess, constantValue);
 82
 083            predicateBody = predicateBody == null ? equality : Expression.AndAlso(predicateBody, equality);
 084        }
 85
 86        // This should not be reached if keyProperties exist and keyValuesToUse is populated.
 087        return predicateBody == null ? null : Expression.Lambda<Func<TEntity, bool>>(predicateBody, parameter);
 088    }
 89}