在将对象传回给调用者/创建者后,一个类属性(很多)会丢失?

时间:2017-11-13 15:39:23

标签: c# visual-studio constructor

我有一个包含两个构造函数的类。

一个构造函数File_Attachment(int Attachment_ID)创建一个类的实例,填充来自单个数据库行的数据。

第二个构造函数File_Attachment(string type, int mid)使用第一个构造函数创建该类的许多实例,并在List<>中收集它们。

以下是完整的类代码:

using System;
using System.IO;
using System.Web;
using System.Collections.Generic;
using System.Data.SqlClient;


public class File_Attachment {

    private string cs = ApplicationData.dbConnectionString;
    private string where = "";

    public List<File_Attachment> File_Attachments = new List<File_Attachment>();

    public int Attachment_ID { get; set; }
    public string Attachment_Type { get; set; }
    public int Attachment_Type_ID { get; set; }
    public int Old_ID { get; set; }
    public string File_Name { get; set; }
    public string Content_Type { get; set; }
    public byte[] Data { get; set; }

    // ****************************************************************************************************************************

    public File_Attachment() {
    }


    // ****************************************************************************************************************************

    public File_Attachment(int Attachment_ID) {

        using (SqlConnection cn = new SqlConnection(cs)) {

            cn.Open();

            using (SqlCommand cmd = new SqlCommand("SELECT * FROM File_Attachments WHERE Attachment_ID = " + Attachment_ID, cn))
            using (SqlDataReader rs = cmd.ExecuteReader()) {

                if (rs.HasRows) {

                    rs.Read();

                    Attachment_ID = (int) rs["Attachment_ID"];
                    Attachment_Type = (string) rs["Attachment_Type"];
                    Attachment_Type_ID = (int) rs["Attachment_Type_ID"];
                    Old_ID = (int) rs["Old_ID"];
                    File_Name = (string) rs["File_Name"];
                    Content_Type = (string) rs["Content_Type"];
                    Data = (byte[]) rs["Data"];

                }
            }
        }

    }

    // ****************************************************************************************************************************

    public File_Attachment(string type, int mid) {

        if (type.ToLower() == "meeting") {
            where = " Attachment_Type = 'Meeting' ";
        }
        if (type.ToLower() == "discussion") {
            where = " Attachment_Type = 'Discussion' ";
        }
        if (type.ToLower() == "action") {
            where = " Attachment_Type = 'Action' ";
        }

        where += " AND Attachment_Type_ID = " + mid.ToString() + " ";

        using (SqlConnection cn = new SqlConnection(cs)) {

            cn.Open();

            using (SqlCommand cmd = new SqlCommand("SELECT * FROM File_Attachments WHERE " + where, cn))
            using (SqlDataReader rs = cmd.ExecuteReader()) {

                if (rs.HasRows) {

                    while (rs.Read()) {

                        File_Attachment fa = new File_Attachment((int)rs["Attachment_ID"]);
                        File_Attachments.Add(fa);

                    }

                }

            }
        }

    }

}

问题是,第二类构造函数使用第一个构造函数创建了许多自身的实例(相同的类)。

在调试期间,在第一个构造函数的代码结束时:

if (rs.HasRows) {

                    rs.Read();

                    Attachment_ID = (int) rs["Attachment_ID"];
                    Attachment_Type = (string) rs["Attachment_Type"];
                    Attachment_Type_ID = (int) rs["Attachment_Type_ID"];
                    Old_ID = (int) rs["Old_ID"];
                    File_Name = (string) rs["File_Name"];
                    Content_Type = (string) rs["Content_Type"];
                    Data = (byte[]) rs["Data"];  //<--------- BREAK POINT!!!!


                }

...所有字段(包括Attachment_ID)都填充了正确的数据。

然而,当List&lt;&gt;收到对象后,列表中的每个实例都会将所有字段 STILL 正确填充数据 EXCEPT Attachment_ID,这些数据全部为零。

请参阅调试器屏幕截图:https://imgur.com/a/Vxftf

令人困惑,因为List&lt;&gt;中的每个对象都是如此。具有适当数据的Attachment_Type_ID,即使它是一个(int)字段,就像Attachment_ID一样。再看看照片。

我考虑过的事情:

最初,在我的visual studio项目中,声明了Attachment_ID:

public int Attachment_ID { get; private set; }

后来改为:

public int Attachment_ID { get; set; }

这是一个缓存问题吗?我已经多次重建了这个解决方案。没有变化。

此外,在数据库中,如果有帮助,Attachment_ID是主键。

我的Attachment_ID在添加到列表的时间和调用者/启动器代码收到列表的时间之间发生了什么?

2 个答案:

答案 0 :(得分:3)

您遇到的一个问题是您使用确切名称声明了一个全局变量作为局部变量。这是有问题的,因为它会导致奇怪的问题。

尝试更换:

public File_Attachment(int Attachment_ID)

使用:

public File_Attachment(int attachmentID)

然后在第一个构造函数中,更改:

using (SqlCommand cmd = new SqlCommand("SELECT * FROM File_Attachments WHERE Attachment_ID = " + Attachment_ID, cn))

为:

using (SqlCommand cmd = new SqlCommand("SELECT * FROM File_Attachments WHERE Attachment_ID = " + attachmentID, cn))

当你这样做时可能会:

Attachment_ID = (int) rs["Attachment_ID"];

您正在将本地变量更改为该值,当构造函数完成时,该值将被丢弃。

作为奖励,您的第一个构造函数应该只将“Attachment_ID”设置为它所采用的参数。您不需要将ID设置为您在数据库中找到的ID,因为您的构造函数将ID作为参数获取。

类似于:

public File_Attachment(int attachmentID){
    Attachment_ID = attachmentID;
    ...

答案 1 :(得分:0)

一年半后重新审视,后来我学到了另一种我更喜欢的方法。

由于该类具有Attachment_ID字段,并且其中一个构造函数具有Attachment_ID参数,因此,如果要引用构造函数参数,请将其保留为“ Attachment_ID”。如果要引用“类”字段/变量,请在其前面加上“ this”关键字。

因此,Attachment_ID是指构造函数参数。

此外,this.Attachment_ID引用了类字段/变量。