Linq: Простая булева функция возвращает linq Исключение

Я видел много плохого кода, написанного на эту тему. Код, который работал для меня, - это (сайт не знает, как правильно проанализировать мой файл кода):

public class Test {

    public static boolean isReachablebyPing(String ip) {

        try {
            String command;

        if(System.getProperty("os.name").toLowerCase().startsWith("windows")) {
            // For Windows
            command = "ping -n 2 " + ip;
        } else {
            // For Linux and OSX
            command = "ping -c 2 " + ip;
        }

        Process proc = Runtime.getRuntime().exec(command);
        StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
        outputGobbler.start();

        proc.waitFor();
        return checkAvailability(outputGobbler.getOutputLines());

        } catch(IOException | InterruptedException ex) {
        Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
        }

        return false;
    }

    public static void main(String... args) {

        String ip = "10.20.20.17";   // false in my case
        String ip1 = "10.20.20.100"; // true in my case

        System.out.println(ip + " is avalaible " + isReachablebyPing(ip));
        System.out.println(ip1 + " is avalaible " + isReachablebyPing(ip1));
    }

    private static boolean checkAvailability(List<String> outputLines) {

        for(String line : outputLines) {
            if(line.contains("unreachable")) {
                return false;
            }
            if(line.contains("TTL=")) {
                return true;
            }
        }
        return false;

    }

}

class StreamGobbler extends Thread {

    protected InputStream is;

    protected String type;

    protected List<String> outputLines;

    StreamGobbler(InputStream is, String type) {
        this.is = is;
        this.type = type;
        outputLines = new ArrayList<>();
    }

    public List<String> getOutputLines() {
        return outputLines;
    }

    @Override
    public void run() {
        try {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line;
            while((line = br.readLine()) != null) {
                outputLines.add(line);
            }
        } catch(IOException ex) {
                Logger.getLogger(StreamGobbler.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}
8
задан jlembke 3 November 2009 в 00:24
поделиться

5 ответов

Другой способ - использовать предикат Expression > ...

var query = from x in table where SomeFunctionReturnsBool() select;

Изменить: Я обычно не делаю этого способ, который я показал выше ... Я только что понял это из кода выше. Вот как я обычно это реализую. Потому что тогда вы можете добавить дополнительные методы Enumerable или закомментировать их во время отладки.

var results = table.Where(SomeFunctionReturnsBool())
    .OrderBy(yt => yt.YourProperty)
    //.Skip(pageCount * pageSize) //Just showing how you can easily comment out parts...
    //.Take(pageSize)
    .ToList(); //Finally executes the query...

private Expression<Func<YourType, boo>> SomeFunctionReturnsBool()
{
    return (YourType yt) => yt.YourProperty.StartsWith("a")
        && yt.YourOtherProperty == true;
}

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

7
ответ дан 5 December 2019 в 12:59
поделиться

Это можно сделать в LINQ-to-SQL, создав UDF, сопоставленный с контекстом данных; для этого нужно написать TSQL и использовать ctx.SomeFunctionblah (...).

Альтернативой является работа с деревьями выражений - например, это может быть:

Expression<Func<Customer, bool>> SomeFunc() {
    return c => true; // or whatever
}

и использование .Where (SomeFunc ()) - это достаточно близко? В этом случае вы не можете использовать синтаксис запроса, но он выполняет свою работу ...


Добавлен хитрый метод Where , чтобы показать, как вы можете использовать его в синтаксисе запроса . Я не полагаю, что это фантастика, но вы можете найти это удобным.

using System;
using System.Linq;
using System.Linq.Expressions;

static class Program
{
    static void Main()
    {
        using (var ctx = new NorthwindDataContext())
        {
            ctx.Log = Console.Out;
            // fluent API
            var qry = ctx.Customers.Where(SomeFunc("a"));
            Console.WriteLine(qry.Count());

            // custom Where - purely for illustration
            qry = from c in ctx.Customers
                  where SomeFunc("a")
                  select c;
            Console.WriteLine(qry.Count());
        }
    }
    static IQueryable<T> Where<T>(this IQueryable<T> query,
        Func<T, Expression<Func<T, bool>>> predicate)
    {
        if(predicate==null) throw new ArgumentNullException("predicate");
        return query.Where(predicate(default(T)));
    }
    static Expression<Func<Customer, bool>> SomeFunc(string arg)
    {
        return c => c.CompanyName.Contains(arg);
    }
}
3
ответ дан 5 December 2019 в 12:59
поделиться

По сути, «из коробки» у вас не может быть LINQ-to-SQL для выполнения запросов, содержащих пользовательские функции. Фактически можно использовать только некоторые собственные методы, которые могут быть переведены в SQL.

Самый простой способ обойти это, к сожалению, может повлиять на производительность в зависимости от того, сколько данных вы возвращаете из БД.

В принципе, вы можете только используйте пользовательские функции в статусах WHERE, если данные уже были загружены в память, т. е. SQL уже был выполнен.

Самое быстрое исправление для вашего примера будет выглядеть так:

var query = from x in table.ToList() where SomeFunctionReturnsBool() select;

Обратите внимание на ToList (). Он выполняет SQL и помещает данные в память. Теперь вы можете делать все, что хотите, в операторе / методе WHERE.

2
ответ дан 5 December 2019 в 12:59
поделиться

Я бы просто разбил их так:

Expression<Func<Table, bool>> someTreeThatReturnsBool = x => true;

var query = from x in table where someTreeThatReturnsBool select x;

Вы можете создавать функции, которые передают деревья выражений.

1
ответ дан 5 December 2019 в 12:59
поделиться

Не используйте для этого синтаксис запроса.

var query = table.Where( x => SomeFunction(x) );
0
ответ дан 5 December 2019 в 12:59
поделиться
Другие вопросы по тегам:

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