C # linq select new statement dynamic item [duplicate]

Когда вы конвертируете .1 или 1/10 в base 2 (двоичный), вы получаете повторяющийся шаблон после десятичной точки, точно так же, как пытаетесь представить 1/3 в базе 10. Значение не является точным, и поэтому вы можете 't делать точную математику с ней, используя обычные методы с плавающей запятой.

7
задан thndrwrks 11 February 2016 в 19:15
поделиться

5 ответов

Не уверен, что вы здесь. Но это должно дать вам Идею.

var query = db.Mytable.Where(x=> x.Specialty == criteria[0].Value && c=> c.Rank == criteria[1].Value).ToString(); 

Я даже не уверен, почему вам даже нужно использовать List. Поскольку Список необходимо повторить. Вы можете просто использовать Key first First Condition и Value для последнего условия, чтобы избежать списка KeyValuePair.

0
ответ дан Aizen 28 August 2018 в 00:44
поделиться

Хорошо. Позвольте мне дать мои два цента. Если вы хотите использовать динамический LINQ, то вам следует использовать деревья выражений. Вы можете генерировать операторы LINQ как динамические, как вы хотите. Что-то вроде следующего должно делать волшебство.

// inside a generic class.
public static IQueryable<T> GetWhere(string criteria1, string criteria2, string criteria3, string criteria4)
{
    var t = MyExpressions<T>.DynamicWhereExp(criteria1, criteria2, criteria3, criteria4);
    return db.Set<T>().Where(t);
}

Теперь в другом родовом классе вы можете определить свои выражения как.

public static Expression<Func<T, bool>> DynamicWhereExp(string criteria1, string criteria2, string criteria3, string criteria4)
{
    ParameterExpression Param = Expression.Parameter(typeof(T));

    Expression exp1 = WhereExp1(criteria1, criteria2, Param);
    Expression exp2 = WhereExp1(criteria3, criteria4, Param);

    var body = Expression.And(exp1, exp2);

    return Expression.Lambda<Func<T, bool>>(body, Param);
}

private static Expression WhereExp1(string field, string type, ParameterExpression param) 
{
    Expression aLeft = Expression.Property(param, typeof(T).GetProperty(field));
    Expression aRight = Expression.Constant(type);
    Expression typeCheck = Expression.Equal(aLeft, aRight);
    return typeCheck;   
}

Теперь вы можете вызвать методы где угодно.

// get search criterias from user
var obj = new YourClass<YourTableName>();
var result = obj.GetWhere(criteria1, criteria2, criteria3, criteria4);

Это даст вам мощное динамическое выражение с двумя условиями с оператором AND между ними для использования в вашем методе расширения LINQ. Теперь вы можете передать свои аргументы, как хотите, на основе вашей стратегии. например в параметрах string [] или в списке пар ключей значения ... не имеет значения.

Вы можете видеть, что здесь ничего не исправлено. Его полностью динамический и быстрый, чем отражение, и вы делаете столько выражений и столько же критериев ...

0
ответ дан Awais Mahmood 28 August 2018 в 00:44
поделиться

Непрерывный ответ @ Jakotheshadows, но не требующий дополнительных проверок на выходе EF, когда нет ничего, что можно проверить, это ближе к тому, что мы делаем здесь:

// Example lists, a solution for populating will follow
var Names = new List<string> { "Adam", "Joe", "Bob" };
// These two deliberately left blank for demonstration purposes
var specialties = new List<string>();
var ranks = new List<string>();
using(var dbContext = new MyDbContext())
{
    var list = dbContext.MyTable
       .FilterByNames(names)
       .FilterBySpecialties(specialties)
       .FilterByRanks(ranks)
       .Select(...)
       .ToList();
}

Таблица

[Table(...)]
public class MyTable : IMyTable
{
    // ...
}

Фильтр по расширениям

public static class MyTableExtensions
{
    public static IQueryable<TEntity> FilterMyTablesByName<TEntity>(
        this IQueryable<TEntity> query, string[] names)
        where TEntity : class, IMyTable
    {
        if (query == null) { throw new ArgumentNullException(nameof(query)); }
        if (!names.Any() || names.All(string.IsNullOrWhiteSpace))
        {
            return query; // Unmodified
        }
        // Modified
        return query.Where(x => names.Contains(x.Name));
    }
    // Replicate per array/filter...
}

Кроме того, существуют значительные проблемы с производительностью при использовании Contains (...) или Any (...) внутри запроса EF. Существует более быстрый метод использования Predicate Builders. Это пример с массивом идентификаторов (для этого требуется пакет nuget LinqKit):

public static IQueryable<TEntity> FilterByIDs<TEntity>(
    this IQueryable<TEntity> query, int[] ids)
    where TEntity : class, IBase
{
    if (ids == null || !ids.Any(x => x > 0 && x != int.MaxValue)) { return query; }
    return query.AsExpandable().Where(BuildIDsPredicate<TEntity>(ids));
}
private static Expression<Func<TEntity, bool>> BuildIDsPredicate<TEntity>(
    IEnumerable<int> ids)
    where TEntity : class, IBase
{
    return ids.Aggregate(
        PredicateBuilder.New<TEntity>(false),
        (c, id) => c.Or(p => p.ID == id));
}

Это выводит синтаксис «IN» для очень быстрого запроса:

WHERE ID IN [1,2,3,4,5]
0
ответ дан James Gray 28 August 2018 в 00:44
поделиться

Поскольку ваши столбцы и фильтры динамические, вам может помочь библиотека Dynamic LINQ

NuGet: https://www.nuget.org/packages/System.Linq.Dynamic/

Doc: http://dynamiclinq.azurewebsites.net/

using System.Linq.Dynamic; //Import the Dynamic LINQ library

//The standard way, which requires compile-time knowledge
//of the data model
var result = myQuery
    .Where(x => x.Field1 == "SomeValue")
    .Select(x => new { x.Field1, x.Field2 });

//The Dynamic LINQ way, which lets you do the same thing
//without knowing the data model before hand
var result = myQuery
    .Where("Field1=\"SomeValue\"")
    .Select("new (Field1, Field2)");

Другое решение - использовать Eval Expression.NET , который позволяет вам динамически оценивать код c # во время выполнения.

using (var ctx = new TestContext())
{
    var query = ctx.Entity_Basics;

    var list = Eval.Execute(@"
q.Where(x => x.ColumnInt < 10)
 .Select(x => new { x.ID, x.ColumnInt })
 .ToList();", new { q = query });
}

Отказ от ответственности: Я являюсь владельцем проекта Eval Expression.NET

Редактировать: ответьте комментарий

Будьте осторожны, тип значения параметра должен быть совместим с типом свойства. Например, если свойство «Ранг» является INT, будет работать только тип, совместимый с INT (не строка).

Очевидно, вам нужно будет реорганизовать этот метод, чтобы сделать его более подходящим для вашего приложения. Но, как вы можете видеть, вы можете легко использовать даже метод async из Entity Framework.

Если вы также настроили select также (тип возврата), вам может понадобиться либо получить результат async с помощью отражения, либо вместо этого использовать ExecuteAsync с ToList ().

public async Task<List<Entity_Basic>> DynamicWhereAsync(CancellationToken cancellationToken = default(CancellationToken))
{
    // Register async extension method from entity framework (this should be done in the global.asax or STAThread method
    // Only Enumerable && Queryable extension methods exists by default
    EvalManager.DefaultContext.RegisterExtensionMethod(typeof(QueryableExtensions));

    // GET your criteria
    var tuples = new List<Tuple<string, object>>();
    tuples.Add(new Tuple<string, object>("Specialty", "Basket Weaving"));
    tuples.Add(new Tuple<string, object>("Rank", "12"));

    // BUILD your where clause
    var where = string.Join(" && ", tuples.Select(tuple => string.Concat("x.", tuple.Item1, " > p", tuple.Item1)));

    // BUILD your parameters
    var parameters = new Dictionary<string, object>();
    tuples.ForEach(x => parameters.Add("p" + x.Item1, x.Item2));

    using (var ctx = new TestContext())
    {
        var query = ctx.Entity_Basics;

        // ADD the current query && cancellationToken as parameter
        parameters.Add("q", query);
        parameters.Add("token", cancellationToken);

        // GET the task
        var task = (Task<List<Entity_Basic>>)Eval.Execute("q.Where(x => " + where + ").ToListAsync(token)", parameters);

        // AWAIT the task
        var result = await task.ConfigureAwait(false);
        return result;
    }
}
9
ответ дан Jonathan Magnan 28 August 2018 в 00:44
поделиться

Попробуйте это как общий шаблон для динамических предложений where:

//example lists, a solution for populating will follow
List<string> Names = new List<string>() { "Adam", "Joe", "Bob" };
//these two deliberately left blank for demonstration purposes
List<string> Specialties = new List<string> () { };
List<string> Ranks = new List<string> () { };
using(var dbContext = new MyDbContext())
{
    var list = dbContext.MyTable
                        .Where(x => (!Names.Any() || Names.Contains(x.Name)) &&
                                    (!Specialties.Any() || Specialties.Contains(x.Specialty)) &&
                                    (!Ranks.Any() || Ranks.Contains(x.Rank))).ToList();

}

Сделав некоторые предположения относительно ваших базовых данных, следующим является SQL, который, вероятно, будет сгенерирован LINQ, показанный выше:

DECLARE @p0 NVarChar(1000) = 'Adam'
DECLARE @p1 NVarChar(1000) = 'Joe'
DECLARE @p2 NVarChar(1000) = 'Bob'

SELECT [t0].[Name], [t0].[Specialty], [t0].[Rank]
FROM [MyTable] AS [t0]
WHERE [t0].[Name] IN (@p0, @p1, @p2)

Чтобы заполнить эти списки в вашем классе UserSearch:

foreach(var kvp in criteria)
{
    switch(kvp.Key)
    {
        case "Name": Names.Add(kvp.Value); break;
        case "Specialty": Specialties.Add(kvp.Value); break;
        case "Rank": Ranks.Add(kvp.Value); break;
    }
}

Если вы заинтересованы в ремонтопригодности и что столбцы таблицы будут часто меняться, тогда вы можете захотеть вернуться к использованию raw SQL через класс SqlCommand. Таким образом, вы можете легко создавать динамические выделения и предложения. Вы даже можете запросить список столбцов в таблице, чтобы динамически определить, какие параметры доступны для выбора / фильтрации.

1
ответ дан Ofiris 28 August 2018 в 00:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: