Круто, но это именно то, что делает первый блок кода в моем ответе;)

ел бы добавить проверку в нашем хранилище, которая отфильтровывает все объекты по идентификатору компании, если он есть и соответствует ли он заданному значению.

Итак, где мы имеем:

public T First<T>(Expression<Func<T, bool>> expression) where T : EntityObject  
{  
   var set = GetObjectSet<T>();  
   return set.FirstOrDefault<T>();  
}  

Я хотел бы добавить строку, которая выглядит что-то, где ...

express.And("Check for CompanyId property if it exists then make sure it = 3");  

Есть идеи, как это сделать?
Спасибо :)

Ответы на вопрос(3)

которую можно использовать для привязки проверки идентификатора компании к вашему выражению, если идентификатор идентификатора компании существует в сущности, это должно помочь:

public static Expression<Func<T, bool>> CheckPropertyIfExists<T, TProperty>(Expression<Func<T, bool>> expression, string propertyName, TProperty propertyValue)
{
    Type type = typeof(T);
    var property = type.GetProperty(propertyName, typeof(TProperty));
    if(property == null || !property.CanRead)
        return expression;

    return expression.Update(
        Expression.And( // && 
            Expression.Equal( // ==
                Expression.MakeMemberAccess(expression.Parameters[0], property), // T parameter.{propertyName}
                Expression.Constant(propertyValue) // specified propertyValue constant
            ),
            expression.Body // Original expression
        ),
        expression.Parameters
    );
}

Вы можете использовать это так:

public T First<T>(Expression<Func<T, bool>> expression, int companyId)
{
    var set = GetObjectSet<T>();  
    return set.FirstOrDefault<T>(CheckPropertyIfExists(expression, "CompanyId", companyId));  
}

И теперь вы можете позвонитьFirst метод с вашим выражением и компанией, которую вы хотите отфильтровать.

Несколько лучшим способом сделать это может быть использование его в качестве метода фильтрации, то есть переписать его как метод расширения, который не требует внутреннего выражения и работает с запросом объекта (или IQueryable):

public static ObjectQuery<T> FilterByPropertyIfExists<T, TProperty>(this ObjectQuery<T> query, string propertyName, TProperty propertyValue)
{
    Type type = typeof(T);
    var property = type.GetProperty(propertyName, typeof(TProperty));
    if(property == null || !property.CanRead)
        return query;

    var parameter = Expression.Parameter(typeof(T), "x");
    Expression<Func<T, bool>> predicate = (Expression<Func<T, bool>>)Expression.Lambda(
        Expression.Equal( // ==
            Expression.MakeMemberAccess(parameter, property), // T parameter.{propertyName}
            Expression.Constant(propertyValue) // specified propertyValue constant
        ),
        parameter
    );
    return query.Where(predicate);
}

Прелесть этого в том, что он будет очень хорошо работать со стандартными синтаксисами LINQ (как запросов, так и свободно).

например это позволяет запросы как это:

from x in repository.Clients.FilterByPropertyIfExists("Company", 5)
where x == ???
select x.Name;

[РЕДАКТИРОВАТЬ]

Я немного очистил его и добавил проверку видимости параметра (должно быть открытым, статическим свойством), а также реализацию ObjectQuery (которая будет автоматически использоваться для ObjectQuery и ObjectSet):

public static class QueryExtensions
{
    public static IQueryable<T> FilterByPropertyIfExists<T, TProperty>(this IQueryable<T> query, string propertyName, TProperty propertyValue)
    {
        Type type = typeof(T);
        var property = type.GetProperty(
            propertyName, 
            BindingFlags.Instance | BindingFlags.Public, // Must be a public instance property
            null, 
            typeof(TProperty), // Must be of the correct return type
            Type.EmptyTypes, // Can't have parameters
            null
        );
        if (property == null || !property.CanRead) // Must exist and be readable
            return query; // Return query unchanged

        // Create a predicate to pass to the Where method
        var parameter = Expression.Parameter(typeof(T), "it");
        Expression<Func<T, bool>> predicate = (Expression<Func<T, bool>>)Expression.Lambda(
            Expression.Equal( // ==
                Expression.MakeMemberAccess(parameter, property), // T parameter.{propertyName}
                Expression.Constant(propertyValue) // specified propertyValue constant
            ),
            parameter
        );
        return query.Where(predicate); // Filter the query
    }

    public static ObjectQuery<T> FilterByPropertyIfExists<T, TProperty>(this ObjectQuery<T> query, string propertyName, TProperty propertyValue)
    {
        var filteredQuery = FilterByPropertyIfExists((IQueryable<T>)query, propertyName, propertyValue);
        return (ObjectQuery<T>)filteredQuery; // Cast filtered query back to an ObjectQuery
    }
}
 Bennor McCarthy25 янв. 2011 г., 00:58
Да, это я протестировал, и он работает с LINQ to Entities. Он также должен работать с LINQ to SQL. Он по-прежнему может быть переведен в операторы SQL, потому что ничего не вводит и не появляется ни в одном простом предложении where. Он по-прежнему ограничен теми же правилами, что и L2E, то есть он не будет работать сenum стоимость.
 Slauma25 янв. 2011 г., 00:46
Вау, это выглядит интересно! Как вы думаете, он также будет работать с LINQ to Entities? Например: используя вашCheckPropertyIfExists в качестве предикатаFirstOrDefaultбудет ли это работать в LINQ to Entities? (Насколько я понимаю, предикат должен быть переведен в операторы SQL и что я могу использовать только «канонические функции» внутри предиката, но я не совсем уверен, как все это подробно описывается.)
 Slauma25 янв. 2011 г., 01:39
Большой! Я поиграю с этим, когда у меня будет немного времени. Я не знал, чтоExpression Класс предлагает так много и мощных функций.
 Bennor McCarthy25 янв. 2011 г., 02:23
Да, деревья выражений действительно великолепны, но поначалу они немного сложны. :)

Я взял то, что вы положили туда, и создал метод расширения, который добавляет фильтр «И» к существующему выражению.

    public static Expression<Func<T, bool>> AddEqualityCheck<T, TProperty>(this Expression<Func<T, bool>> expression, string propertyName, TProperty propertyValue)
    {
        Type type = typeof(T);
        var property = type.GetProperty(
            propertyName,
            BindingFlags.Instance | BindingFlags.Public,
            null,
            typeof(TProperty),
            Type.EmptyTypes,
            null
        );

        if (property == null || !property.CanRead)
        {
            return expression;
        }
        else
        {
            var equalityExpression = Expression.Equal(
                Expression.MakeMemberAccess(expression.Parameters[0], property),
                Expression.Constant(propertyValue)
                );
            var andEqualityExpression = Expression.And(equalityExpression, expression.Body);
            return expression.Update(andEqualityExpression, expression.Parameters);
        }
    }
 Bennor McCarthy25 янв. 2011 г., 20:16
Круто, но это именно то, что делает первый блок кода в моем ответе;)

public interface ICompanyFilterable
{
  int CompanyId { get; set; }
}

public partial class YourEntity : ICompanyFilterable
{
    ....
}

public static IQueryable<T> FilterByCompanyId<T>(this IQueryable<T> query, int companyId)
    where T : ICompanyFilterable
{
    return query.Where(e => e.CompanyId == companyId);
}

Ваш ответ на вопрос