【问题标题】:populating A Class that has another class as a property填充具有另一个类作为属性的类
【发布时间】:2015-06-27 02:58:34
【问题描述】:

我的 Windows 窗体应用程序中有两个类。 假设StudentStudentDetailsStudentDetails 也是Student 类的属性。

我有一个从数据库中的两个表中获取数据的存储过程。 我需要知道这种情况通常是如何处理的,这意味着学生类通常是如何填充的。 非常感谢你的回答。 任何指向类似场景的链接都会很棒。

这是我的代码:

 class Student
    {
        public int StudentID { get; set; }
        public string StudentName { get; set; }
        public StudentDetails StudentDetails { get; set; }

        public Student()
        {
            this.StudentID = 0;
            this.StudentName = String.Empty;
            this.StudentDetails = new StudentDetails();
        }

    }

class StudentDetails
    {

        public int StudentDetailsID { get; set; }
        public string Address { get; set; }
        public int Height { get; set; }
        public int Weight { get; set; }

        public StudentDetails()
        {
            this.StudentDetailsID = 0;
            this.Address = String.Empty;
            this.Height = 0;
            this.Weight = 0;

        }

    }

下面的类有一个填充学生类的函数(FillStudent()

 Class StudentAssembler
        {

            public List<Model.Student> FillStudent()
            {
                List<Model.Student> StudentCollection = new List<Model.Student>();
                Model.Student StudentDTO = new Model.Student();
                try
                {
                    using (Model.dbConnection dbconnection = new Model.dbConnection(Utilities.SqlConnStr))
                    {

                        SqlDataReader dr;
                        SqlCommand command = new SqlCommand("GetStudents", dbconnection.connection);
                        command.CommandType = CommandType.StoredProcedure;
                        dbconnection.OpenConn();
                        dr = command.ExecuteReader();
                        while (dr.Read())
                        {
                            StudentDTO.StudentID = dr[0] == DBNull.Value ? 0 : (int)dr[0];
                            StudentDTO.StudentName = dr[1] == DBNull.Value ? String.Empty : (String)dr[1];

//this is the part that i need to know how is it usually handled

//StudentDTO.StudentDetails = how to fill out this part ???
                                StudentCollection.Add(StudentDTO);
                            }

                            return StudentCollection;
                        }
                    }
                    catch (Exception)
                    {
                        return null;
                    }
                }
            }

编辑:

存储过程代码

select s.StudentID,s.StudentName,sd.StudentDetailsID,sd.Address,
sd.Height,sd.Weight
from Student s,StudentDetails sd
where s.StudentID = sd.StudentID

【问题讨论】:

  • 这取决于“GetStudents”过程返回的内容。如果详细信息在那里,您可以简单地创建一个 StudentDetails 的新实例并设置属性。这不是处理这种事情的好方法吗?为什么不使用实体框架?
  • @Pseudonym:“代码损坏,请帮助”在 Code Review 中明确不在主题范围内。花点时间回顾一下那里可以提出什么样的问题:codereview.stackexchange.com/help/dont-ask
  • @Pseudonym 感谢您的评论,实际上我并没有使用发布的代码我只是把它作为一个例子我只需要帮助找到如何处理类似的场景什么是最佳实践或最佳设计模式:)
  • @Andrew 存储过程代码已发布,非常感谢
  • @nayefharb 似乎您的程序返回了您需要的一切。我发布了一个简单修复的答案。

标签: c# class oop design-patterns properties


【解决方案1】:

考虑到存储过程查询,您可以简单地:

StudentDTO.StudentDetails = new StudentDetails
{
    StudentDetailsID = dr[2] == DBNull.Value ? 0 : (int)dr[2],
    Address = dr[3] == DBNull.Value ? String.Empty : (String)dr[3],
    ...
};

【讨论】:

    【解决方案2】:

    你有两个选择

    1:一个单独的 sproc(或 sql),用于通过 studentID 从学生详细信息表中获取信息。每个学生都叫这个

    2:在 sproc/sql 中加入学生详细信息表,并使用同一行数据填充两者

    选项 1:通常更清洁且更可重用。我会说这应该是您的第一种方法。

    但是,如果您需要检索许多学生,选项 2 会快得多。因为它只需要一次调用数据库。

    此外,您似乎在学生和学生详细信息之间存在一对一的关系,因此没有理由不使用选项 2。但是,如果您对一个学生有很多详细信息,您仍然可以使用选项 2,跳过重复的学生信息。即使您从 sql 返回的数据多于所需的数据,这通常也是最好的方法

    【讨论】:

    • 关于我第一次尝试的第一个选项,但我想寻找更好的方法(如果存在)。关于第二个选项,如果我错了,请纠正我,我现在将有 3 个 DataObjects Student、StudentDetails 和一个用于我的存储过程的单独的我认为这会导致不必要的代码重复。
    • 您不需要创建第三个 dto,只需填充两者
    【解决方案3】:

    您可以创建单独的函数来获取学生和学生详细信息记录。 这样你就可以在代码的任何地方重复使用这些函数。

    例如对于student,你可以有这样的功能

      public Student CreateStudent(IDataRecord iDataRecord)
        {
            Student stud = new Student();
            stud.Id = GetValue<int>(iDataRecord, "Id");
            stud.Name = GetValue<string>(iDataRecord, "Name");
            return stud;
        }
    

    对于studentDetails,创建一个这样的函数:

          public StudentDetails CreateStudentDetails(IDataRecord iDataRecord)
        {
            StudentDetails studDetails = new StudentDetails();
            studDetails.Id = GetValue<int>(iDataRecord, "Id");
            studDetails.Address = GetValue<string>(iDataRecord, "Address");
            studDetails.Height = GetValue<string>(iDataRecord, "Height");
            studDetails.Weight = GetValue<string>(iDataRecord, "Weight");
            return studDetails;
        }
    

    然后,在您的 FillStudent 方法中,只需调用:

    Student student=this.CreateStudent(dr);
    student.StudentDetails=this.CreateStudentDetails(dr);
    

    请注意,此代码仅用于说明目的。您可以进一步重构此代码以将其单独放置以创建工厂类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-17
      • 2021-12-04
      • 2019-09-05
      • 1970-01-01
      • 1970-01-01
      • 2018-08-19
      • 1970-01-01
      相关资源
      最近更新 更多