ASP.Net: 寻找设计视图模型和模型代码的正确方法

ASP.Net: Looking for right approach to design view model and model code

我是 ASP.Net MVC 的新手。在我的项目中,我没有使用 Entity Framework,而是使用 ADO.net。这是我的视图模型设计的代码。请看

动作

public class WebGrid_Sample1Controller : Controller
    {
        // GET: WebGrid
        public ActionResult Show1(StudentVm oSVm)
        {
            StudentVm SVm = new StudentVm(); //.GetStudents(oSVm);
            SVm.Students= SVm.GetStudents(oSVm);
            return View(SVm);
        }
    }

我的模型和视图模型代码

public class StudentVm
    {
        public int page { get; set; }
        public int RowCount { get; set; }
        public int PageSize { get; set; }
        public int CurrentPage { get; set; }

        public string sort { get; set; }
        public string sortdir { get; set; }

        public IList<Student> Students { get; set; }

        public StudentVm()
        {
            PageSize = 5;
            sort = "ID";
            sortdir = "ASC";
            CurrentPage = 1;
        }

        public IList<Student> GetStudents(StudentVm oSVm)
        {
            int StartIndex = 0, EndIndex = 0;

            if (oSVm.page == 0)
                oSVm.page = 1;

            StartIndex = ((oSVm.page * oSVm.PageSize) - oSVm.PageSize) + 1;
            EndIndex = (oSVm.page * oSVm.PageSize);
            CurrentPage = StartIndex;

            if (string.IsNullOrEmpty(oSVm.sort))
                oSVm.sort = "ID";

            if (string.IsNullOrEmpty(oSVm.sortdir))
                oSVm.sortdir = "ASC";

            string connectionStringName = System.Configuration.ConfigurationManager.ConnectionStrings["StudentDBContext"].ConnectionString;
            IList<Student> _Student = new List<Student>();

            string strSQL = "SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
            strSQL += " ORDER BY " + oSVm.sort + " " + oSVm.sortdir;

            strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
            using (SqlConnection connection = new SqlConnection(connectionStringName))
            {
                SqlCommand command = new SqlCommand(
                  strSQL, connection);

                connection.Open();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        _Student.Add(new Student()
                        {
                            ID = Convert.ToInt32(reader["ID"].ToString()),
                            FirstName = reader["FirstName"].ToString(),
                            LastName = reader["LastName"].ToString(),
                            IsActive = Convert.ToBoolean(reader["IsActive"]),
                            StateName = reader["StateName"].ToString(),
                            CityName = reader["CityName"].ToString()
                        });
                    }
                }

                reader.NextResult();
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        RowCount = Convert.ToInt32(reader["Count"].ToString());
                    }
                }

                reader.Close();
            }
            //RowCount = _Student.Count;
            return _Student;
        }
    }

型号

public class Student
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsActive { get; set; }
    public string StateName { get; set; }
    public string CityName { get; set; }
}

有人查看我的视图模型代码并说 视图模型不应包含实现。 View Models 是在客户端、控制器和视图之间传递数据的容器。

他给出了vm code

的新局部设计
public class StudentVm
{
    public int page { get; set; }
    public int RowCount { get; set; }
    public int PageSize { get; set; }
    public int CurrentPage { get; set; }
    public string sort { get; set; }
    public string sortdir { get; set; }
    public IList<Student> Students { get; set; }
}

public class Student
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool IsActive { get; set; }
    public string StateName { get; set; }
    public string CityName { get; set; }
}

public ActionResult Index()
{
    return View();
}

[HttpPost]
public ActionResult Show1(StudentVm oSVm)
{
    return View(oSVm);
}

所以我的问题是将数据库交互例程放在哪里?

我说的是这一行

public IList<Student> GetStudents(StudentVm oSVm)
        {
            int StartIndex = 0, EndIndex = 0;

            if (oSVm.page == 0)
                oSVm.page = 1;

            StartIndex = ((oSVm.page * oSVm.PageSize) - oSVm.PageSize) + 1;
            EndIndex = (oSVm.page * oSVm.PageSize);
            CurrentPage = StartIndex;

            if (string.IsNullOrEmpty(oSVm.sort))
                oSVm.sort = "ID";

            if (string.IsNullOrEmpty(oSVm.sortdir))
                oSVm.sortdir = "ASC";

            string connectionStringName = System.Configuration.ConfigurationManager.ConnectionStrings["StudentDBContext"].ConnectionString;
            IList<Student> _Student = new List<Student>();

            string strSQL = "SELECT ID, FirstName,LastName,IsActive,StateName,CityName FROM vwListStudents WHERE ID >=" + StartIndex + " AND ID <=" + EndIndex;
            strSQL += " ORDER BY " + oSVm.sort + " " + oSVm.sortdir;

            strSQL += ";SELECT COUNT(*) AS Count FROM vwListStudents";
            using (SqlConnection connection = new SqlConnection(connectionStringName))
            {
                SqlCommand command = new SqlCommand(
                  strSQL, connection);

                connection.Open();

                SqlDataReader reader = command.ExecuteReader();

                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        _Student.Add(new Student()
                        {
                            ID = Convert.ToInt32(reader["ID"].ToString()),
                            FirstName = reader["FirstName"].ToString(),
                            LastName = reader["LastName"].ToString(),
                            IsActive = Convert.ToBoolean(reader["IsActive"]),
                            StateName = reader["StateName"].ToString(),
                            CityName = reader["CityName"].ToString()
                        });
                    }
                }

                reader.NextResult();
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        RowCount = Convert.ToInt32(reader["Count"].ToString());
                    }
                }

                reader.Close();
            }
            //RowCount = _Student.Count;
            return _Student;
        }

所以我的要求是任何人都可以使用数据库交互例程重构我的代码。 如何设计整个代码,包括 viewmodel、model 和 db interaction 例程。我正在使用 ADO.Net。到目前为止,无论我阅读什么示例文章来重构我的代码,所有项目示例都使用 EF。所以请有人用数据库交互例程重组我的代码。提前致谢。

不要在视图模型中混合使用数据访问代码。这违背了关注点分离的全部目的。引入视图模型的整个想法是不要将 ORM 端实体混合到视图层。

您的视图模型应该是 lean-flat POCO/DTO 类。这些 DTO 用于在一层与另一层之间传输数据。它应该不知道从哪里获取数据。

您应该有另一个 layer/class,它将为您提供数据,并且您会将实体映射到您的视图模型。如果您不喜欢手动映射,可以使用像 Automapper 这样的映射库来实现。

您可以根据应用的复杂程度以多种不同的方式设计您的 application/layers。一个快速简单的实现就像

YourProject.Common :该项目将 DTO's/POCO 存储在您的项目中。如果需要,您可以根据需要将视图模型保留在这里。

YourProject.Data :此项目引用了您的通用项目和 returns 数据,格式为那些 DTO 类。

YourProject.Web/UI:您的 Web/API 项目。这将引用 Data 项目和 Commin 项目并调用数据访问方法来获取数据。您可以在此处执行 属性 映射(从实体读取并设置为查看模型)。

您可以向堆栈添加更多层,例如 UI 和数据访问之间的 Business/Service 层 以执行一些业务逻辑/映射等..

明智地使用分层,如果你盲目地试图创建很多实际上不需要的层,你最终会弄得一团糟。

您需要做的第一件事是将 db-access 代码移出您的视图模型并移入存储库 class。请参阅下面的示例:

public class WebGridSampleController
{
    private StudentRepository _data;

    public WebGridSampleController()
    {
        _data = new StudentRepository();
    }

    public ActionResult Show1(StudentVm oSVm)
    {
        var students = _data.GetStudents(oSVm.page, oSVm.pageSize, oSVm.sort, oSVm.sortDir);
        oSVm.Students = students.ToList();
        return View(oSVm);
    }
}

public class StudentRepository
{
    public IEnumerable<Student> GetStudents(int page, int pageSize, string sort, string sortDir)
    {
        // Put the code that you have in StudentVM.GetAllStudents here
    }
}

您发布的代码还有其他问题。我认为其中大部分归结为 classes 和变量的命名不当。例如:这里的景色是什么?它不是查看特定学生的详细信息,是吗?

因此,StudentVm(或 StudentViewModel)可能应该命名为 StudentListViewModel.另外,Controller 应该命名为 StudentController,因为它控制着学生的观看。此外,在我看来,动作 Show1 应该被称为 List

考虑到这些,示例可以更新如下:

public class StudentController
{
    private StudentRepository _data;

    public StudentController()
    {
        _data = new StudentRepository();
    }

    public ActionResult List(StudentListViewModel viewModel)
    {
        var students = _data.GetStudents(viewModel.Page, viewModel.PageSize, viewModel.Sort, viewModel.SortDirection);
        viewModel.Students = students.ToList();
        return View(viewModel);
    }
}

public class StudentRepository
{
    public IEnumerable<Student> GetStudents(int page, int pageSize, string sort, string sortDir)
    {
        // Put the code that you have in StudentVM.GetAllStudents here
    }
}

我们也可以解决依赖注入的话题,但目前似乎有点过头了。另外,此时我不会为每个 "layer" 创建一个项目。只需确保您的模型和视图模型不引用任何数据访问内容。