循环创建并向ArrayList添加新对象

时间:2015-10-13 19:26:30

标签: c# sql arraylist

编辑以避免阅读整篇文章 tldr:除非您希望该对象的所有实例具有该字段的相同值,否则对象的字段不应该是静态的

我正在尝试创建并填充Blog对象的ArrayList。我确实知道这样做的通用方法:

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

但是,当我尝试在while(datareader.read())循环中执行此操作时,ArrayList中的所有元素都是完全相同的Blog。具体来说,我最终得到一个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表中最后一篇博客的指针。我想ArrayList allBlogs看起来像[b,b,b,... b],因此当我说b.setTitle()等时它们都会更新。但是如果我创建一个新的Blog对象,情况怎么样呢?在每次迭代开始时?

以下是一些您不必阅读的额外信息,但可能会对问题的结构产生一些疑惑:

  1. Blog对象具有id,title和message字段及其各自的getter / setter
  2. Kristina_Blogs是一个表格,代表这些博客,其中包含id,title,message
  3. 建议说要为我的数据库引擎添加标记,但我找不到它的标记:Microsoft SQL Server Management Studio
  4. 当我使用字符串的ArrayList而不是Blogs
  5. 时,此代码可以正常工作

    编辑:包含来自Blog类的代码

    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; }
    
    }
    

4 个答案:

答案 0 :(得分:3)

正如我在评论中提到的,您遇到的主要问题是您的成员变量是静态的,因此当您设置值时,它们会在所有实例中发生变化。你应该这样改变你的代码:

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时,它将在该calss的所有实例之间共享。
  • 在C#中,您可以使用property来获取或设置值,当您获得某个属性的值时,您不需要setXsetY { {1}}该属性的代码将执行,当您为属性赋值时,它的get部分将执行。您可以这样定义属性:

属性:

set

或更简单:

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

答案 1 :(得分:2)

Blog类中的所有字段都是静态的,这意味着它们在所有对象实例之间共享。您希望它们是实例字段(意思不是static),以便每个对象都有自己的每个值的副本。

答案 2 :(得分: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关键字,您允许对象的不同实例保存不同的值。

现在,每次创建博客对象时,该对象的标题和消息等都将包含自己的信息。

答案 3 :(得分:0)

我会快速制作一个方法来防止null值抛出错误

    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);
        }

其中number是记录中字段的索引,并假设“id”是整数。还要考虑在循环外部移动“博客”对象的创建,只需更改值。