2015-10-13 2 views
1

Редактировать, чтобы спасти вас от чтения через весь этот пост tldr: поля объекта не должно быть статическим, если вы не хотите, чтобы все экземпляры этого объекта, чтобы иметь такое же значение для этого поляLooping Создание и добавление новых объектов в ArrayList

Я пытаюсь создать и заполнить объекты ArrayList для Blog. Я знаю общий способ сделать это:

create ArrayList of Blogs 
loop (some condition) 
    create new Blog 
    add this Blog to AL 

Однако, когда я пытаюсь сделать это в цикле while(datareader.read()), все элементы в ArrayList точно так же блог. В частности, я заканчиваю тем, что ArrayList заполнен несколькими указателями на самый последний объект Blog из таблицы базы данных. Вот мой код:

public static ArrayList AllBlogs() 
    { 
     SqlDataReader dr = anonPage.ExecuteReader("SELECT * FROM Kristina_Blogs"); 

     ArrayList allBlogs = new ArrayList(); 

     if (dr.HasRows) 
     { 
      while (dr.Read()) 
      { 
       Blog b = new Blog(); 

       //grab a row from Kristina_Blogs and assign those attributes to b 
       b.setTitle(dr["title"].ToString()); 
       b.setMessage(dr["message"].ToString()); 
       b.setId(dr["id"]); 

       allBlogs.Add(b); 
      } 
     } 
     dr.Close(); 
     return allBlogs; 
    } 

Как я уже говорил ранее, результатом этого является ArrayList заполнены указателями на самый последний блог из таблицы Kristina_Blogs. Я предполагаю, что allBlogs ArrayList выглядит как [b, b, b, ... b], и поэтому они ВСЕ обновляются, когда я говорю b.setTitle() и т. Д. Но как это может быть, если я создаю объект NEW Blog в начале каждой итерации?


Вот некоторые дополнительные Информация о том, что вы не должны читать, но это могло бы прояснить некоторую путаницу о структуре задачи:

  1. Блог объект имеет поля ID, название и сообщение и их соответствующие получатели/сеттеры
  2. Kristina_Blogs - это таблица, представляющая эти блоги с колонками для идентификатора, заголовка, сообщения
  3. Предложения включают в себя тег для моего механизма БД, но я не могу найти для него тег: Microsoft Студия управления SQL Server
  4. Этот код прекрасно работает, когда я использую ArrayList цепочек вместо блогов

Edit: Включая код из блога класса

public class Blog 
{ 
    public App myApp; 
    public static string Title; 
    public static string Message; 
    public static int Id; 

    //constructors 
    public Blog() { } 
    public Blog(App App) { this.myApp = App; } 

    //all getters and setters look like this 
    public string getTitle() { return Title; } 
    public void setTitle(string t) { Title = t; } 

} 
+1

не отвечает на ваш вопрос, но подумайте об использовании списка вместо ArrayList. ArrayList был выбором до дженериков и типизированной коллекции (начиная с .Net 2, если я не ошибаюсь) –

+2

Лучше поделиться своим кодом «Блог». Я думаю, проблема заключается в том, что ваш класс 'Blog' имеет статические переменные-члены. –

+0

Также лучше использовать свойства для установки значений вместо 'setX' и' setY' –

ответ

2

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

public class Blog 
{ 
    public int Id { get; set; } 
    public string Title { get; set; } 
    public string Message { get; set; } 
} 

и заполнить свой список таким образом, не забудьте добавить using System.Linq;:

var result = new List<Blog>(); 
var connection = @"your connection string"; 
var command = "SELECT * FROM Kristina_Blogs"; 
var adapter = new System.Data.SqlClient.SqlDataAdapter(command, connection); 
var dataTable = new DataTable(); 

//Get data 
adapter.Fill(dataTable); 

dataTable.Rows.Cast<DataRow>().ToList() 
      .ForEach(row => 
      { 
       var b = new Blog(); 
       b.Id = row.Field<int>("Id"); 
       b.Title = row.Field<string>("Title"); 
       b.Message = row.Field<string>("Message"); 

       result.Add(b); 
      }); 

return result; 

Примечание:

  • При создании член static, он делится между всеми экземплярами этих изображений.
  • В C# вы можете использовать property, чтобы получить или установить значение, вам не нужно setX или setY, когда вы получаете значение свойства, то get код этого свойства будет выполняться и при присвоении значения к свойство set часть его будет выполнена. Вы можете определить свойства таким образом:

недвижимости:

private int id; 
public int Id 
{ 
    get 
    { 
     return id; 
    } 
    set 
    { 
     id = value; 
    } 
} 

или более просто:

public int Id { get; set; } 
2

Все поля в вашем Blog класса являются статическими, смысл они распределяются между всеми объектными экземплярами. Вы хотите, чтобы они были полем экземпляра (то есть не static), чтобы каждый объект имел свою собственную копию каждого из этих значений.

0

Удалить статические атрибуты из вашего класса:

public class Blog 
{ 
    public App myApp; 
    public String Title; 
    public String Message; 
    public int Id; 

//constructors 
public Blog() { } 
public Blog(App App) { this.myApp = App; } 

//all getters and setters look like this 
public String getTitle() { return Title; } 
public String getMessage() { return Message; } 
public void setTitle(String t) { Title = t; } 
public void setMessage(String m) { Message = m; }  

} 

При использовании static переменных, все экземпляры объекта будут содержать одни и те же значения в этих переменных. Удалив ключевое слово static, вы позволяете различным экземплярам объекта хранить разные значения.

Теперь, каждый раз, когда вы создаете объект блога, заголовок и сообщение этого объекта и т. Д., Будут содержать свою собственную информацию.

+0

О, ладно, спасибо. Я не знаю, почему я сделал эти статические в первую очередь, но сейчас все работает. Если я хочу, чтобы все блоги были связаны с одним и тем же приложением, должен ли я сделать поле myApp статическим? – Kristina

+0

Конечно, но если вы измените переменную App для одного блога, она изменится для ВСЕХ блогов. – Sterls

0

Я хотел бы сделать быстрый метод, чтобы предотвратить нулевое значение от броска ошибки

public static string GetSafeString(SqlDataReader reader, int index) 
    { 
     if (!reader.IsDBNull(index)) 
      return reader.GetString(index); 
     else 
      return string.Empty; 
    } 

Заменить этот код:

 while (dr.Read()) 
     { 
      Blog b = new Blog(); 

      //grab a row from Kristina_Blogs and assign those attributes to b 
      b.setTitle(dr["title"].ToString()); 
      b.setMessage(dr["message"].ToString()); 
      b.setId(dr["id"]); 

      allBlogs.Add(b); 
     } 

С помощью этого кода:

  while (dr.Read()) 
     { 
      Blog b = new Blog(); 

      //grab a row from Kristina_Blogs and assign those attributes to b 
      b.setId(dr.GetInt32(0)); 
      b.setTitle(GetSafeString(dr, 1); 
      b.setMessage(GetSafeString(dr, 2); 
      allBlogs.Add(b); 
     } 

Если число является индексом поля в записи и при условии, «идентификатор» представляет собой целое число. Также рассмотрите возможность перемещения объекта «Блог» за пределы цикла и просто изменение значений.

Смежные вопросы