3

我正在使用 .net 构建我的第一个 Web 应用程序,它需要与一个非常大的现有数据库进行交互。我已经建立了连接,并创建了一个类,我可以调用它来构建传递几个参数的选择、插入、更新和删除查询。

我可以通过在按钮单击中编写我想要的查询来连接,但我想知道这是最好的解决方案吗?这种方式似乎很难调试,因为它将数据库代码与其他代码混合在一起。

过去(在其他语言中)我创建了一个类,该类将包含所有数据库查询字符串和参数,其余代码将调用它们。这样,如果像存储过程参数这样简单的事情发生变化,代码就都在一个地方。

当我在.net 中查找此内容时,我看不到以这种方式执行此操作,并且我热衷于学习最佳实践。

    protected void Button1_Click(object sender, EventArgs e)
    {
       NameLabel.Text = UserNoTextBox.Text;

       string spName = "SP_SelectUser";
       SqlParameter[] parameters = new SqlParameter[]
       {
           new SqlParameter("@User_No", UserNoTextBox.Text)
       };

       DataAccess dbAccess = new DataAccess();

       DataTable retVal = dbAccess.ExecuteParamerizedSelectCommand(spName, CommandType.StoredProcedure, parameters);
 }

更新:我所指的类是来自以下网站的 DataAccess 类:http: //www.codeproject.com/Articles/361579/A-Beginners-Tutorial-for-Understanding-ADO-NET (类可在http: //www.codeproject.com/script/Articles/ViewDownloads.aspx?aid=361579 )

更新:最后我选择了将 MVC 3 与 Entity Framework 一起使用——太棒了!

4

4 回答 4

6

这是一个巨大的话题,但一个非常简短的观点可能如下:

  1. DataTable必须死(好吧,它有一些用途,但总的来说:它必须死);考虑使用自定义类型,例如:

    public class User {
        public int Id {get;set;}
        public string Name {get;set;}
        public string EmployeeNumber {get;set;}
        // etc
    }
    

    还应该注意的是,许多 ORM 工具会从底层表结构中 为您生成这些。

  2. 不要混合 UI 和数据访问;将此代码分开,理想情况下分成单独的类,但至少分成单独的方法:

    protected void Button1_Click(object sender, EventArgs e)
    {
        NameLabel.Text = UserNoTextBox.Text;
        var user = SomeType.GetUser(UserNoTextBox.Text);
        // do something with user
    }
    ...
    public User GetUser(string userNumber) {
       ... your DB code here
    }
    
  3. 使用诸如 ORM(EF、LINQ-to-SQL、LLBLGenPro)或 micro-ORM(dapper、PetaPoco 等)之类的库 - 例如,这是带有 dapper 的代码:

    public User GetUser(string userNumber) {
        using(var conn = GetOpenConnection()) {
            return conn.Query<User>("SP_SelectUser",
            new {User_No = userNumber}, // <=== parameters made simple
            commandType: CommandType.StoredProcedure).FirstOrDefault()
        }
    }
    

    或使用 LINQ-to-SQL(EF 非常相似):

    public User GetUser(string userNumber) {
        using(var db = GetDataContext()) {
            return db.Users.FirstOrDefault(u => u.User_No == userNumber);
        }
     }
    
  4. 并非所有内容都需要是存储过程;两者之间曾经存在巨大的性能差异 - 但现在情况已不再如此。使用它们有充分的理由(非常精细的安全性、与多个应用程序消费者共享数据库、认为自己是开发人员的 dba),但它们也会产生维护问题,尤其是在部署更改时。在大多数情况下,我会毫不犹豫地使用原始(但参数化的)SQL,例如:

    public User GetUser(string userNumber) {
        using(var conn = GetOpenConnection()) {
            return conn.Query<User>(@"
    select [some columns here]
    from Users where User_No = @userNumber",
            new {userNumber}).FirstOrDefault()
        }
    }
    
于 2012-08-30T10:10:36.497 回答
4

我会做这样的事情:

后面的代码

protected void Button1_Click(object sender, EventArgs e)
{
    UserController uc = new UserController();
    User u = UserController.GetUser(Convert.ToInt32(UserNoTextBox.Text);
    NameLabel.Text = u.UserName;
}

在你的UserController.cs

class UserController{
    public User GetUser(int userId)
    {
        return DataAccess.GetUser(userId);
    }
}

在你的User.cs

class User{
    private string _userName;
    public string UserName{ get{ return _userName;} set{ _userName= value;} }
}

并在您的DataAccess.cs中使用Dapper

public User GetUser(int id)
{
    var user = cnn.Query<User>("SP_SelectUser", new {User_No = id}, 
        commandType: CommandType.StoredProcedure).First();
    return user;
}     

这只是一种选择,但你也可以使用不同的ORM的,这是关于个人风格的。这是.Net ORM 的列表

祝你好运!

于 2012-08-30T10:04:12.373 回答
1

在 OOP 世界中,一般的最佳实践往往与语言无关。您说您过去曾在其他 OOP 语言中使用过数据访问,因此在 .net 中也会这样做。有关一般最佳实践的良好链接,请参阅@Oded 的回复。

如果您正在寻找有关如何最好地使用 .net 数据访问技术的指导,请尝试以 MSDN 关于 ADO 的文章为起点。

于 2012-08-30T10:03:33.717 回答
0

您正在做的事情会起作用,但没有遵循良好的 OOP 原则,其中之一是关注点分离- 您的 UI 不应该直接与数据库对话。

您应该将所有数据访问代码放在 UI 层可以调用的单独层中。

另请参阅SOLID 原则不要重复自己


与数据库交互时,许多人使用 ORM - 实体框架、nHibernate、Dapper 和许多其他存在于 .NET 应用程序的工具。这些充当数据访问层,您应该调查它们在您的应用程序中的使用情况。

于 2012-08-30T09:46:48.917 回答