Public Function GetUserList() As DataTable
Dim resultTable As New DataTable
Dim queryString As String = "SELECT NAME, ID FROM user"
...
myDataAdapter.Fill(resultTable)
...
Return resultTable
End Function
VS
Public Function GetUserList() As List(Of User)
Dim resultList As New List(Of User)
Dim queryString As String = "SELECT NAME, ID FROM user"
...
Do While(myDataReader.Read())
resultList.add( _
new User(myDataReader.GetString(0),myDataReader.GetInt32(1)))
Loop
...
Return resultList
End Function
第二种方法告诉函数调用者期望返回类型,所以它应该更好。问题是它需要不同的类来保存不同查询的返回值!
当你有50个只用于一个或两个函数的类似结构的类时,我无法想象它会非常“干净”吗?我错过了什么吗?
编辑:澄清我的问题:我应该为1个查询创建1个类还是其他更好的练习?
答案 0 :(得分:2)
如果你正在处理一个带有几个表和几个查询的简单小项目,那么为每个查询编写一个类可能是要走的路。但我使用大约20个不同的(活动)应用程序使用大约20个不同的数据库,表格范围从10到200个表格,每个查询每个类别的手写不仅需要50%的时间,而且需要花费50%的时间维护的时间,现在的工作时间。
我所拥有的是一个读取数据库模式的简单程序(基于我选择的表/视图/ SP)为每个对象创建一个类。这用于保存数据,而不是查询数据。事件虽然您可能不会每次都返回所有行,但您仍然可以将结果放在同一个类中。例如,您从USER表中获取了ID和NAME。您的班级/表格可能包含更多字段,但您只需填写ID和NAME即可。如果您在其他查询中需要更多信息,例如EMAIL或其他内容,那么您也可以填写它。
现在,生成自己的类的一个问题是,如果你需要根据某些计算创建一些自定义属性,你想在你的类中做到这一点,但是下次从模式重新生成类时,比如说添加字段或表,您在生成的类中编写的自定义属性将被覆盖。这就是为什么你应该为你生成的代码创建一个BASE类,然后为你的自定义代码创建另一个继承自该类的类。
这可能听起来令人困惑,但一旦开始这样做真的很简单。第一步是创建应用程序/工具来生成类。这只是读取数据库的模式(你可以找到各种各样的帖子,了解如何为你正在使用的数据库做什么),并使用像IO.StreamWritter
之类的东西,创建CLS
文件的方式如上所示,你想要它们。
然后让它为每个表创建第二个类(这将是您的自定义代码类),但前提是它已经不存在。在这个类中,您希望从其他类继承。
现在,当您使用数据(查询,迭代等)时,您将使用自定义类。为了方便起见,你不要混淆,你可以给你的基类提供一个很好的命名约定(比如MyTable_BASE),然后你的自定义类就会成为你的表的名字。
您要做的最后一步是创建一个类/ dll,您可以在应用程序中使用它来运行查询并为您填写数据。您不希望为每个查询和结果创建一个新类,因此执行一些通用的填充类是最好的方法。这会产生一个更高级别的难度,因为要一般地填充它,所有基类都应该从单个泛型类继承。这个类会知道它是数据以及如何存储它但不知道有关特定数据的任何信息。然后,您获取数据的方法将填充这些基础类。
对于所有这一切还有一点,但是如果你决定走这条路的话,你会在你走的时候想出来。下面我介绍了一些简单的类,让您了解该过程。他们并没有真正按原样工作,因为我采取了一些自由来保持代码简短。
这是一个用于保存数据的简单类。这是您生成的所有类应继承的类:
Public Class MyBaseEntity
Private _DR as DataRow
Public sub New(byval DR as dataRow)
_DR = DR
End Sub
End Class
接下来是您生成的类,基于对象的模式(表,视图等)所有这些代码都将由您的应用/工具生成:
Public Class MyTable_BASE
Inherits MyBaseEntity
'Your code for NEW that calls the base class here
Public property ID as int32
Get
return _DR("ID")
End Get
'Code for setter
End Property
'More code for each property/field in your table
最后一个是你的自定义类。您可能并不总是使用它,但是一旦您真正开始这样做,它就非常有用。只有在不存在时才会生成此类(以防止覆盖自定义代码):
Public Class MyTable
Inherits MyTable_BASE
'Your code for NEW that calls the base class here
End Class
然后,如果你有一些你想做的事情的计算,你可以把它放在那个班级。例如,如果您有ORDERS表,则应存储价格和数量,但不存储总数。但是,在您的GUI中,您需要显示总数,以便在最后一个类中创建一个属性,该属性将根据价格和数量计算总数。
Public Readonly Property Total as Decimal
Get
Return Price * Quantity
End Get
End Property
我想要分享的最后一件事是用于实例化这些类的示例代码,因为如果您创建一个用于保存查询结果的通用方法,则您不知道应该返回的类型(您的自定义类)。 / p>
我有几种方法,但还有更多方法。
Public Function GetMyData(Byval SQL as string,Byval ReturnType as type) as MyBaseEntity()
'...Your code to connect to database and get data into datarows here
Dim aRet as new arraylist
For i As Int32 = 0 To DT.Rows.Count - 1
aRet.Add(Activator.CreateInstance(ReturnType, DT.Rows(i))
Next
Return aRet.ToArray(ReturnType)
End Function
或者,您可以使用Generics
:
Public Function GetMyData(of T)(Byval SQL as string) as List(oF T)
'...Your code to connect to database and get data into datarows here
'...Similar type of code here, you get the idea.
End Function