Member 13637561 Ответов: 2

Оператор Oracle SELECT в C# возвращает только первую строку несколько раз


-У меня есть простой оператор select (с соединением) из двух таблиц.
-Пока читатель читает это, я создаю новый экземпляр, а затем вызываю свои классы, которые будут содержать информацию из каждого столбца моей таблицы.
-Тогда я добавлю этот экземпляр в конец списка.

Но после нескольких недель отладки я понял, что по какой-то причине новый экземпляр " d " в этом случае не создается. Таким образом, каждый раз, когда он проходит через извлечение информации из классов, он одновременно заменяет предыдущий массив в списке. Это приводит к тому, что каждый раз создается одна и та же строка. Вот мой код.

public List<Donor> Get()
        {
            //Define fields
            List<Donor> donors = new List<Donor>();
            string query;
            OracleCommand cmd;
            OracleDataReader reader;

            query = "SELECT * FROM ldhc_accounts l JOIN donors d ON l.donor_id = d.id";
            conn.Open();
            cmd = new OracleCommand(query, conn);
            reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                Donor d = new Donor();
                {
                    d.DonorId = Convert.ToInt32(reader["id"]);
                    d.FName = reader["fname"].ToString();
                    donors.Add(d);
                }

            }

            conn.Close();

            return donors;
        }



Файл C# :

protected void get_donors_btn_Click(object sender, EventArgs e)
        {
            List<Donor> donors = a_oracle.Get();
            foreach(Donor item in donors)
            {
                get_donors.InnerHtml += "<li>"
                    + item.DonorId + " " 
                    + item.FName + " "
                    + "</li>";
            }
        }


Класс Доноров

namespace FinalProj.Models
{
    public class Donor : ldhc
    {
        //Fields
        private static Int64 _donor_credit_card;
        private static int _donor_ccv;
        private static int _donor_expiry_month;
        private static int _donor_expiry_year;
        private static int _donor_amt;
        private static int _donor_rows;
        private static object _donor_id;

        //Methods
        public int Donor_Amt
        {
            get { return _donor_amt; }
            set { _donor_amt = value; }
        }

        public Int64 DonorCredit
        {
            get { return _donor_credit_card; }
            set { _donor_credit_card = value; }
        }

        public int DonorCCV
        {
            get { return _donor_ccv; }
            set { _donor_ccv = value; }
        }

        public int DonorExpMonth
        {
            get { return _donor_expiry_month; }
            set { _donor_expiry_month = value; }
        }
        
        public int DonorExpYear
        {
            get { return _donor_expiry_year; }
            set { _donor_expiry_year = value; }
        }

        public int DRows
        {
            get { return _donor_rows; }
            set { _donor_rows = value; }
        }

        public object DonorId
        {
            get { return _donor_id; }
            set { _donor_id = value; }
        }

        //public ldhc Ldhc { get; set; }
    }
}


Что я уже пробовал:

-Я попытался перестроить, где создается мой новый экземпляр, я трижды проверил весь мой другой код и, наконец, понял, что здесь что-то не так.

-Если я создаю оператор select и включаю предложение WHERE, он отлично работает и возвращает только одну строку, которая мне нужна.

-Я удалил некоторые другие столбцы, которые пытаюсь восстановить, чтобы сделать этот код немного чище, но когда я запускаю этот оператор select в SQL developer, он отлично работает, возвращая 3 отдельные строки.

-Я в тупике. Переполнение стека поставлено в тупик (или это слишком многословный вопрос).

-Дайте мне знать, если вам понадобится еще какая-нибудь информация.

Paulo Zemek

Этот код выглядит нормально... у него есть какая-то странная область видимости (почему после Donor d = new Donor();?)

Возможно ли, что в вашем реальном коде вы делаете Donor d = new Donor() до этого времени? Это объяснило бы проблему (вы бы читали и перечитывали/заменяли содержимое на d и добавляли один и тот же d много раз в список, делая его похожим на последнюю запись, много раз).

Edit: когда я говорю "Хорошо", я имею в виду, что ожидаю, что код будет работать. Я бы предложил использовать предложения "using" для команды и читателя. Также желательно объявлять переменные с инициализацией в одной строке, но это не должно влиять на корректность кода.

Member 13637561

Спасибо за ответ - я вырезал и вставил именно то, что у меня есть, и я уверен, что новый экземпляр будет создан внутри while. Меня предупреждали, что мой код определенно нуждается в некоторой полировке, но теоретически я знаю, что это должно сработать... Я просто не знаю, почему это не так, или если я упускаю что-то еще.

Paulo Zemek

Кто вызывает Get()? Возможно ли, что вызывающий Get() на самом деле делает что-то не так?

Как я вижу из вашего комментария к OriginalGriff, похоже, что данные заменяются (таким образом, остается только последняя строка, а не первая), и это было бы больше похоже на то, что я ожидал, если бы d создавался вне цикла.

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

Member 13637561

Я добавил код для вызова Get() - я совершенно уверен, что это не проблема, потому что я вижу, что список заполняется одной и той же строкой каждый раз с предыдущей функцией, поэтому мой C# просто отображает список, который я заполнил.

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

Paulo Zemek

Извините, но вы сказали мне, что вырезаете/вставляете именно то, что у вас есть... но это определенно не так.

Вы передаете аргумент a_oracle.Get() (что a_donor), но код, который вы показываете для Get (), не получает никаких параметров.

Итак, это даже не компилируется... Итак, вы действительно вырезали/вставили именно то, что у вас есть?

Member 13637561

Я вырезал и вставил неправильный код C# - у меня действительно нет никаких причин лгать о вырезании и вставке...

Paulo Zemek

Я вижу новый код.
Что ж... честно говоря, я не знаю, что случилось. Помимо "очистки" кода, я не вижу в нем никаких ошибок.

Richard Deeming

Код выглядит так, как будто он должен работать и для меня тоже.

Ты делаешь что-нибудь странное в своей жизни? Donor класс?

Member 13637561

Я так не думаю...
Я загрузил все, что есть в моем классе доноров.

Я также должен упомянуть, что у меня есть пара перегрузок для этой функции

Richard Deeming

Ну, вот и ответ. :)

2 Ответов

Рейтинг:
16

Richard Deeming

В вашем Donor класс, вы объявили все поля как static.

Это означает, что для этих полей всегда существует только одно значение, независимо от того, сколько экземпляров вашего класса вы создаете.

Снимите крышку static модификатор из полей, и ваш код должен работать.

public class Donor : ldhc
{
    //Fields
    private Int64 _donor_credit_card;
    private int _donor_ccv;
    private int _donor_expiry_month;
    private int _donor_expiry_year;
    private int _donor_amt;
    private int _donor_rows;
    private object _donor_id;

статические (Справочник по c#) | Майкрософт документы[^]


Member 13637561

ВЫ. Ты мой герой.
Словами не передать, как я благодарен за то, что наконец нашел ответ на эту проблему.
Спасибо!

Рейтинг:
1

OriginalGriff

Без доступа к вашим данным мы мало что можем сделать.
Что - то, что вы можете попробовать-вместо DataReader используйте DataAdapter и заполните DataTable.
Затем вы можете использовать отладчик, чтобы точно увидеть, сколько строк вы получаете обратно и что именно они содержат. Маловероятно, что конструктор - донор возвращает один и тот же экземпляр каждый раз - это потребовало бы некоторого серьезного изменения способа работы конструкторов объектов,-поэтому гораздо более вероятно, что возвращаемые данные кажутся идентичными в каждой строке, а не повторное использование одного и того же экземпляра объекта.


Member 13637561

Я определенно попробую DataAdapter, но из того, что я вижу в отладчике, он проходит через каждую строку, и данные собираются. Но после создания нового экземпляра и прохождения данных следующей строки первый элемент в списке заменяется новыми данными, и так далее...