<commit_before>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using Common.Utilites;

namespace Common.Extensions
{
    public static class EntityExtensions
    {
        private static Expression<Func<TEntity, bool>> GetExpression<TEntity>(
           params object[] key)
           where TEntity : class
        {
            var keyProps = EntityUtilites<TEntity>.KeyProps;
            if (key.Count() != keyProps.Count()) return null;

            var entityType = typeof(TEntity);
            var entityParameter = Expression.Parameter(entityType, "p");
            var expressions = new List<BinaryExpression>();

            var i = 0;
            foreach (var part in keyProps)
            {
                var property = Expression.Property(entityParameter, part.Name);
                var genericType = typeof(TypeUtilites<>).MakeGenericType(property.Type);
                var tryConvertValue = genericType.GetMethod("TryConvertValue",
                    new[] { typeof(object), property.Type.MakeByRefType() });
                object[] args = { key[i++], null };
                var result = (bool)tryConvertValue.Invoke(null, args);
                if (!result) return null;
                var constant = Expression.Constant(args[1]);
                var equal = Expression.Equal(property, constant);
                expressions.Add(equal);
            }

            var body = expressions.Aggregate(Expression.And);
            var expression = Expression.Lambda<Func<TEntity, bool>>(body, entityParameter);

            return expression;
        }

        public static TEntity Find<TEntity>(
           this IQueryable<TEntity> source,
           params object[] key)
           where TEntity : class
        {
            var expression = GetExpression<TEntity>(key);

            var call = Expression.Call(
                typeof(Queryable),
                "FirstOrDefault",
                new[] { source.ElementType },
                source.Expression,
                Expression.Quote(expression)
                );

            return source.Provider.Execute<TEntity>(call);
        }

        public static TEntity Exist<TEntity>(
           this IQueryable<TEntity> source,
           params object[] key)
           where TEntity : class
        {
            var expression = GetExpression<TEntity>(key);

            var call = Expression.Call(
                typeof(Queryable),
                "Any",
                new[] { source.ElementType },
                source.Expression,
                Expression.Quote(expression)
                );

            return source.Provider.Execute<TEntity>(call);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]<commit_msg>* fix returned type in Exist method<commit_after>﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using Common.Utilites;

namespace Common.Extensions
{
    public static class EntityExtensions
    {
        private static Expression<Func<TEntity, bool>> GetExpression<TEntity>(
           params object[] key)
           where TEntity : class
        {
            var keyProps = EntityUtilites<TEntity>.KeyProps;
            if (key.Count() != keyProps.Count()) return null;

            var entityType = typeof(TEntity);
            var entityParameter = Expression.Parameter(entityType, "p");
            var expressions = new List<BinaryExpression>();

            var i = 0;
            foreach (var part in keyProps)
            {
                var property = Expression.Property(entityParameter, part.Name);
                var genericType = typeof(TypeUtilites<>).MakeGenericType(property.Type);
                var tryConvertValue = genericType.GetMethod("TryConvertValue",
                    new[] { typeof(object), property.Type.MakeByRefType() });
                object[] args = { key[i++], null };
                var result = (bool)tryConvertValue.Invoke(null, args);
                if (!result) return null;
                var constant = Expression.Constant(args[1]);
                var equal = Expression.Equal(property, constant);
                expressions.Add(equal);
            }

            var body = expressions.Aggregate(Expression.And);
            var expression = Expression.Lambda<Func<TEntity, bool>>(body, entityParameter);

            return expression;
        }

        public static TEntity Find<TEntity>(
           this IQueryable<TEntity> source,
           params object[] key)
           where TEntity : class
        {
            var expression = GetExpression<TEntity>(key);

            var call = Expression.Call(
                typeof(Queryable),
                "FirstOrDefault",
                new[] { source.ElementType },
                source.Expression,
                Expression.Quote(expression)
                );

            return source.Provider.Execute<TEntity>(call);
        }

        public static bool Exist<TEntity>(
           this IQueryable<TEntity> source,
           params object[] key)
           where TEntity : class
        {
            var expression = GetExpression<TEntity>(key);

            var call = Expression.Call(
                typeof(Queryable),
                "Any",
                new[] { source.ElementType },
                source.Expression,
                Expression.Quote(expression)
                );

            return source.Provider.Execute<bool>(call);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
{'fraction_non_alphanumeric': 0.09501061571125266, 'fraction_numerical': 0.0007077140835102619, 'mean_word_length': 1.8307461191787682, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2736823', 'n_tokens_mistral': 1399, 'n_tokens_neox': 1328, 'n_words': 313}