Какая оценка функции требует запуска всех потоков? - PullRequest
0 голосов
/ 04 мая 2020

Я только что создал таблицу Cust и в Ado. net и создал dbEntity для использования LINQ

Но я получаю эту ошибку и не могу получить записи.

  protected void Page_Load(object sender, EventArgs e)
    {

        SSEntities db = new SSEntities();


        var a = from tb in db.Custs
                select tb;

    }

ConnectionString -

    <add name="SSEntities" connectionString="metadata=res://*/DbModel.csdl|res://*/DbModel.ssdl|res://*/DbModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=XYZ\SQLEXPRESS;initial catalog=SS;persist security info=True;user id=sa;password=La123;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

Оценка функции ошибки требует запуска всех потоков

Но это работает

     protected void Page_Load(object sender, EventArgs e)
    {

        SSEntities db = new SSEntities();


        var a = db.Custs.FirstOrDefault();

    }

1 Ответ

0 голосов
/ 05 мая 2020

Вы должны знать об отложенном выполнении, которое использует LINQ.

Предполагая, что db.Custs - это объект, реализующий IQueryable<Cust> или что-то подобное.

Если вы проверите введите a в первом примере, вы увидите, что это IQueryable<Cust>. Во втором примере - это Cust.

Если вы изучите методы LINQ, вы заметите, что есть две их группы: те, которые возвращают IEnumerable<TResult> (или IQueryable<TResult>). и те, которые этого не делают.

Select, Join, GroupBy являются примерами первой группы .. не выполняйте запрос. Они не представляют собой извлеченные данные, они представляют собой возможность выбора данных и их перечисления. Пока вы объединяете функции из этой группы. источник ваших данных не запрашивается. Нередко база данных, но это может быть что угодно, перечислимое, читалка CSV-файлов, JSON -файлы, информация из целого rnet. В терминах LINQ говорится, что они используют отложенное выполнение. Вы можете найти этот термин в каждом описании метода.

Примеры методов из второй группы: ToList, FirstOrDefault, Count, Any: возвращается не IQueryable<...>. При выполнении одного из этих методов начнется перечисление IEnumerable / IQueryable, который является источником ввода: будет выбран первый элемент, и если он есть, и если это необходимо для метода, будут получены другие элементы последовательности.

Вернуться к вашему вопросу

Ваша первая загрузка страницы создаст запрос. Создан потенциал для получения данных из вашей базы данных. Увы, вы забыли выполнить запрос. Если вы отлаживаете свою программу и останавливаете все потоки в точке останова и хотите проверить значение a, вы хотите увидеть свойства объекта a. Увы, ваш отладчик готов показать вам результаты простых свойств, но связаться с базой данных для него слишком сложно.

Следовательно, если вы действительно хотите увидеть результат запроса к базе данных во время отладки, вы Придется выполнить запрос, добавив метод второй группы. Чаще всего временно добавляют ToList().

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

Итак, для отладки решение просто: добавьте ToList перед исследованием.

Улучшения

К настоящему времени вы знаете, что переменная a в первом примере выражает возможность получения данных, а не сами полученные данные. Вы, очевидно, упростили свой код для вопроса, вы хотите что-то сделать с данными.

  • Я почти уверен, что SSEntities реализует IDisposable. Вы должны удалить его, как только он вам больше не нужен.
  • Убедитесь, что вы извлекаете данные (выполняете запрос), прежде чем удалять SSEntities.

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

using (SSEntities db = new SSEntities())
{
    var myQuery = db.Custs.Select(cust => new {...});

    // execute the query:
    var fetchedData = myQuery.ToList();
}

Обратите внимание на следующую ловушку:

IQueryable<Cust> GetCustomers()
{
    using (SSEntities db = new SSEntities())
    {
        return db.Custs.Select(cust => new {...});
    }
}

Запрос не выполняется, но вы ' удалил SSEntities. Ваш компилятор не будет жаловаться, вы получите исключение во время выполнения.

Правильное решение - позволить вызывающему абоненту создавать и удалять соединение с базой данных, вы предоставляете только выбор:

static IQueryable<Cust> GetCustomersByPostCode(this IQueryable<Cust> customers,
       PostCode postCode)
{
    return customers.Where(customer => customer.PostCode == postCode)
                    .Select(customer => new {...});
}

Использование:

protected void Page_Load(object sender, EventArgs e)
{
    List<Customer> customers = null;
    using (SSEntities db = new SSEntities())
    {

        PostCode postCode = ...
        customers = db.Customers.GetCustomersByPostCode(postCode).ToList();
    }

    // the database is disposed, cannot be used anymore
    // customers already fetched, can still be used:
    ProcessFetchedCustomers(customers);
}
...