1

我在 vb.net 中做 windows 应用程序。我有客户对象包含保存方法。我如何生成插入查询?

我需要将对象保存在关系数据库(SQL 服务器)中。我需要知道哪种是插入的正确方法,即。在 save 方法中,我编写了 SQL 语句来保存对象。这是正确的方法吗?

谢谢

4

6 回答 6

4

SQL 的简单 INSERT 语句采用以下基本形式:

INSERT INTO [tablename] ( [column1], [column2], ... ) VALUES ( [value1], [value2], ...)

因此,我们显然需要了解您正在使用的数据库表:它有哪些列。我们还需要了解这个类:它有什么属性。最后,我们需要了解表列和类属性的数据类型,以及属性如何映射到列。对于非常简单的对象,名称和类型将对齐。但在其他情况下,您的类本身可能包含一个(或多个)集合,这意味着将数据插入多个表中。

确定了这一切之后,我们仍然需要两件事:数据库的连接信息(通常被提炼成单个连接字符串)以及您是否担心您的类实例之前可能已保存,在这种情况下您想要构建一个 UPDATE 语句而不是 INSERT。

假设您可以以令人满意的方式回答所有这些问题,您的 VB.Net 代码将如下所示(当然,在适当的情况下替换您的特定列、属性、类型和连接信息):

Public Class Customer
    Public Sub Save()
        DAL.SaveCustomer(Me)
    End Sub

    '   ...'

End Class

.

' a VB Module is a C# static class'
Public Module DAL 
    Private ConnString As String = "Your connection string here"

    Public Sub SaveCustomer(ByVal TheCustomer As Customer)
        Dim sql As String = "" & _
        "INSERT INTO [MyTable] (" & _
            "[column1], [column2], ..." & _
        ") VALUES (" & _
            "@Column1, @Column2, ... )"

        Using cn As New SqlConnection(ConnString), _
              cmd As New SqlCommand(sql, cn)

            cmd.Parameters.Add("@column1", SqlDbTypes.VarChar, 50).Value = TheCustomer.Property1
            cmd.Parameters.Add("@column2", SqlDbTypes.VarChar, 1000).Value = TheCustomer.Property2

            cn.Open()
            cmd.ExecuteNonQuery()
        End Using
    End Sub
End Module

我知道您已经听说分离出您的数据库代码是“正确的做法”tm,但我认为您可能还想要一些更具体的原因来说明您希望以这种方式构建代码的原因:

  • 您的连接字符串保存在一个位置,因此如果您的数据库服务器移动,您只需进行一项更改。如果这是它自己的程序集或配置文件,那就更好了。
  • 如果您曾经迁移到完全不同的数据库类型,您只需更改一个文件即可更新程序。
  • 如果你有一个开发人员或 DBA 特别擅长 sql,你可以让他来做这部分应用程序的大部分维护工作。
  • 它使您的“真实”对象的代码更简单,因此当您犯了逻辑设计错误时更容易发现。
  • 如果另一个应用程序想要与同一个数据库通信,则 DAL 代码最终可能是可重用的。
  • 如果您使用 ORM 工具,大部分 DAL 代码都是为您编写的。
于 2008-12-26T19:25:24.737 回答
1

这里有几个问题。首先,你到底在哪里保存这个?您说 SQL,但它是 SQL Server、SQL Express 的实例、本地数据缓存 (SQL CE 3.5) 还是通过 Web 服务保存以与您的 SQL SERVER 对话。这些不同的数据源具有不同的连接选项/要求,并且在 SQL CE 的情况下,SQL 本身还涉及一些其他“陷阱”。

其次,您确定要将数据保存到 SQL Server 等关系数据存储中吗?考虑一下,您可以改用 XML、数据文件(文本、CSV 等)甚至自定义二进制文件类型。

由于您正在使用 Windows 应用程序,因此您可以选择在何处以及如何保存数据。在您知道要将数据放在哪里之前,我们很难帮助您这样做。

于 2008-12-26T18:09:24.830 回答
1

我同意迈克霍弗的观点。将您的对象检索和持久化的类与您的业务类分开是拥有灵活和健壮设计的关键。这是您希望在 GUI 或业务层中看到的那种代码:

//Populate Customer Objects List with data
IList<Customer> customerList = new List<Customer>()
Customer newCustomer1 = new Customer();
newCustomer.Name = "New Name"
newCustomer.email ="abcd@abcd.com"
customerList.Add(newCustomer1)

//DAL calls
DataAccessClass dalClass = new DataAccessClass ();
dalClass.InsertCustomers(customerList);

在您的 DALClass 中应该有一个名为 InsertCustomers(IList customers) 的方法,它应该具有以下代码:

      Public Function InsertCustomers(ByVal objectList As IList(Of Customer)) As Integer
        Dim command As IDbCommand = Nothing
        Dim rowsAffected As Integer = 0
        Dim connection As IDbConnection = New System.Data.SqlClient.SqlConnection(Me.ConnectionString)
        Try 
            connection.Open
            Dim e As IEnumerator = objectList.GetEnumerator

            Do While e.MoveNext

                command = connection.CreateCommand
                command.CommandText = "insert into dbo.Customer(CustomerID,CustomerGUID,RegisterDate,Password,SiteID,Las"& _ 
                    "tName,FirstName,Email,Notes,BillingEqualsShipping,BillingLastName) values (@Cust"& _ 
                    "omerID,@CustomerGUID,@RegisterDate,@Password,@SiteID,@LastName,@FirstName,@Email"& _ 
                    ",@Notes,@BillingEqualsShipping,@BillingLastName)"
                System.Console.WriteLine("Executing Query: {0}", command.CommandText)
                Dim paramCustomerID As IDbDataParameter = command.CreateParameter
                paramCustomerID.ParameterName = "@CustomerID"
                command.Parameters.Add(paramCustomerID)
                Dim paramCustomerGUID As IDbDataParameter = command.CreateParameter
                paramCustomerGUID.ParameterName = "@CustomerGUID"
                command.Parameters.Add(paramCustomerGUID)
                Dim paramRegisterDate As IDbDataParameter = command.CreateParameter
                paramRegisterDate.ParameterName = "@RegisterDate"
                command.Parameters.Add(paramRegisterDate)
                Dim paramPassword As IDbDataParameter = command.CreateParameter
                paramPassword.ParameterName = "@Password"
                command.Parameters.Add(paramPassword)
                Dim paramSiteID As IDbDataParameter = command.CreateParameter
                paramSiteID.ParameterName = "@SiteID"
                command.Parameters.Add(paramSiteID)
                Dim paramLastName As IDbDataParameter = command.CreateParameter
                paramLastName.ParameterName = "@LastName"
                command.Parameters.Add(paramLastName)
                Dim paramFirstName As IDbDataParameter = command.CreateParameter
                paramFirstName.ParameterName = "@FirstName"
                command.Parameters.Add(paramFirstName)
                Dim paramEmail As IDbDataParameter = command.CreateParameter
                paramEmail.ParameterName = "@Email"
                command.Parameters.Add(paramEmail)
                Dim paramNotes As IDbDataParameter = command.CreateParameter
                paramNotes.ParameterName = "@Notes"
                command.Parameters.Add(paramNotes)
                Dim paramBillingEqualsShipping As IDbDataParameter = command.CreateParameter
                paramBillingEqualsShipping.ParameterName = "@BillingEqualsShipping"
                command.Parameters.Add(paramBillingEqualsShipping)
                Dim paramBillingLastName As IDbDataParameter = command.CreateParameter
                paramBillingLastName.ParameterName = "@BillingLastName"
                command.Parameters.Add(paramBillingLastName)
                Dim modelObject As Customer = CType(e.Current,Customer)
                paramCustomerID.Value = modelObject.CustomerID
                paramCustomerGUID.Value = modelObject.CustomerGUID
                paramRegisterDate.Value = modelObject.RegisterDate
                If IsNothing(modelObject.Password) Then
                    paramPassword.Value = System.DBNull.Value
                Else
                    paramPassword.Value = modelObject.Password
                End If
                paramSiteID.Value = modelObject.SiteID
                If IsNothing(modelObject.LastName) Then
                    paramLastName.Value = System.DBNull.Value
                Else
                    paramLastName.Value = modelObject.LastName
                End If
                If IsNothing(modelObject.FirstName) Then
                    paramFirstName.Value = System.DBNull.Value
                Else
                    paramFirstName.Value = modelObject.FirstName
                End If
                If IsNothing(modelObject.Email) Then
                    paramEmail.Value = System.DBNull.Value
                Else
                    paramEmail.Value = modelObject.Email
                End If
                If IsNothing(modelObject.Notes) Then
                    paramNotes.Value = System.DBNull.Value
                Else
                    paramNotes.Value = modelObject.Notes
                End If
                paramBillingEqualsShipping.Value = modelObject.BillingEqualsShipping
                If IsNothing(modelObject.BillingLastName) Then
                    paramBillingLastName.Value = System.DBNull.Value
                Else
                    paramBillingLastName.Value = modelObject.BillingLastName
                End If
                rowsAffected = (rowsAffected + command.ExecuteNonQuery)

            Loop
        Finally
            connection.Close
            CType(connection,System.IDisposable).Dispose
        End Try
        Return rowsAffected
    End Function

手动编写 DAL 代码很痛苦,但是您将完全控制您的 DAL、SQL 和映射代码,并且将来更改其中任何一个都将变得轻而易举。

如果您不想手动编写所有 DAL 代码,您可以使用像Orasis Mapping Studio这样的 CodeGenerator来生成与所示完全相同的代码,而无需编写任何内容。您只需要在工具中构建 SQL,将属性映射到参数即可。它将为您生成所有其余部分。

祝你好运,快乐的 DAL 编码!

于 2008-12-26T21:04:48.720 回答
0

我和斯蒂芬·赖顿在一起。这里有很多变数,还有很多悬而未决的问题。如果是 SQL,它甚至是 SQL 的 Microsoft 方言吗?是甲骨文吗?MySQL?还有什么?

无论如何,我个人的偏好是尽可能避免在应用程序中构建 SQL,并调用存储过程,即使对于插入和更新也是如此。然后我将过程的参数传递给 ADO.NET 命令对象。我脑子里有一个疯狂的想法,即 SQL 属于数据库。也许这来自于我在互联网时代花费大量时间调试将 SQL 字符串拼接在一起的可怕编写的 ASP 代码。(再也不。)

如果您觉得绝对有必要这样做,请参阅System.Text.StringBuilder类。学习它。爱它。让它成为你最好的朋友。

更新: 看到您的回复,我现在看到您正在使用 SQL Server。这让事情变得更好。

我建议将您的 SQL 代码分离到一个单独的类中,远离实际的业务类。有些人可能不同意这一点,但它会使课程的目的保持清晰。(请参阅关注点分离。)

您希望让您的业务对象处理业务逻辑,以及一个单独的类来处理将数据输入和输出数据库的工作。这样,如果您对序列化逻辑有疑问,您就可以更好地了解在哪里查找,并且大大减少了处理业务逻辑的机会。它还使您的应用程序更容易理解。

多写几门课的一点前期努力会在未来获得巨大的回报。

但那只是我的个人意见。

于 2008-12-26T18:21:09.627 回答
0

我更喜欢 Mike Hofer 的想法,在 SQL Server 端有一个存储过程来处理实际的数据更新,并有一个单独的类来包装对这些存储过程的调用。只是我的 0.02 美元

于 2008-12-26T19:25:50.587 回答
0

不太确定OP在问什么。

您需要在“保存”方法中准确定义您在做什么

  • 如果要在 Save 方法中创建新记录,则需要使用 INSERT 语句。
  • 如果要在 Save 方法中更新现有记录,则需要使用 UPDATE 语句。

“保存”方法通常意味着这两种情况都由程序处理。

更好的方法是使用 ("Create" or "Insert") 和 ("Update" or "Save") 方法。

或者也许有一个程序可以同时处理这两种情况。

于 2008-12-26T23:28:08.070 回答