OOP - Where to put the calls to the Data Access Layer? - vb.net

I am implementing a Data Access Layer (DAL), which is basically a set of classes with (VB.NET) Shared functions to actually execute the database (CRUD) calls. I am trying to figure out the best place to place the calls to the DAL within the class hierarchy. Let me give an example.
Suppose I have a class Customer, with only standard ID, Name, Address1, etc. properties and maybe an overridden ToString function or so. I also have a DAL class with Shared methods, such as:
(pseudocode)
Namespace Dal
Public Class Customer
Public Shared Function Read(id As Integer) As Customer
Public Shared Function ReadList() As List(Of Customer)
Public Shared Sub Create(c As Customer)
'etc.
Now, I could call the Dal from the presentation layer like so:
Me.DataGridView1.Datasource = Dal.Customer.ReadList
However, is it not a good practice to have the presentation layer aware of the Dal at all? Should I instead put methods in the Customer object and call the Dal, like this?
Public Function ReadList() As List(Of Customer)
Return Dal.Customer.ReadList()
End Sub
Public Sub Create()
Dal.Customer.Create(Me)
End Sub
Would this be "cleaner" OOP? Or is it acceptable practice to let the presentation call the Dal, passing the business objects like my previous example:
Me.DataGridView1.Datasource = Dal.Customer.ReadList
Dim c As New Customer
c.Name = "Alpha Corporation"
c.Address1 = "123 Main Street"
Dal.Customer.Create(c)
Thanks for your feedback.

The less your application knows about your DAL the better. There are several ways to do this and I think you are on the right track. I think you might want to look into the factory pattern for this implementation as you will be able to hide the DAL implementation behind the factory and return entities and collections of entities from the factory.

I agree that data calls do not belong in a UI layer. Those are for presentation only.
I think they properly belong in a service layer. The service implementation uses model objects and the persistence layer to accomplish its goals. Whether that's an XML-based web service or local interface, the service is the object that maps to use cases and knows about units of work.
Either put the database calls into a separate persistence layer or embed them in the model objects for extra object-oriented purity.

The reason why'd you want to pull the CRUD operations into a separate layer is in case you ever want to change database systems. Well, that's why I did it. I wouldn't recommend doing this just to be good OOD. But here ya go...
Several sets of classes/interfaces
BusinessObject - Represents business type entities such as a Customer, has DataManager as a property.
DataManager - Maybe you can come up with a better name, but this thing provides Load() and Save() functions for the BusinessObjects
SearchList - Returns lists of things, your SQL queries go here. Also this should probably behave like a RecordSet with Next(), Eof(), and CurrentRecord type members
Constructor/Factory - See FactoryPattern. You've de-coupled your database operations from your business objects this thing re-couples them in a necessary way. Assigns an appropriate datamanager implementation to BusinessObject
Come up with whatever actual names you want, but let's talk about Customer again. Suppose you have an Oracle database. You might end up with these classes:
boCustomer that inherits from BusinessObject
oracleDMCustomer that inherits or implements DataManager
searchlistCustomer that inherits from searchlist that has exposed either through abstract methods or as an interface something like:
SearchAll() - which should return all customer
SearchByZip(String zip) which should return all customers with the given zipcode
oracleSearchlistCustomer - implements searchlistCustomer, would actually implement the SearchAll() and SearchByZip()
boFactory - static class that has a method that looks something like CreateObject(Type type)
searchlistFactory - static class that has a method that looks something like CreateSearchList(Type type);
I'll let you fill in some of the blanks, but I think the important stuff is there. Others may have different ideas that require less abstraction. I'd mock up several strategies before going with one.

Related

Interfaces / Classes / Objects and Inheritance

I'm trying to rebuild some old QBASIC (yeah, you read that right) programs for use on more modern systems (because for some reason kids these days don't like DOS).
I understand the basic principles of classes and objects (I think) but I'm obviously missing something.
I have a number of instruments which are controlled using GPIB, using VISA COM libraries. I can make it work, but the code is very ugly :(
In order to use an instrument, I have the following in my Public Class Main:
Public ioMgr As Ivi.Visa.Interop.ResourceManager
Dim myInstrument As New Ivi.Visa.Interop.FormattedIO488
Dim myInstOpen As Boolean
Then, when I come to initializing the instrument (in the 'Initialize' button click sub), I use:
Try
myInstrument.IO = ioMgr.Open("GPIB0::17")
Catch exOpen As System.Runtime.InteropServices.COMException
myInstOpen = False
End Try
Pretty straightforward stuff; if the instrument can't be opened at address 17 on GPIB0, it throws an exception, which gets caught and sets the 'myInstOpen' flag to false.
Then, I can communicate with the instrument using commands from the Ivi.Visa.Interop.FormattedIO488 interface such as:
myInstrument.IO.ReadSTB()
result = myInstrument.ReadString()
myInstrument.WriteString("GPIB Command Here")
And all of it works.
What I want to do is, create a generic 'Instrument' class, that allows me access to all the functions from the Ivi.Visa.Interop.FormattedIO488 interface, and from the Ivi.Visa.Interop.ResourceManager interface, but also allows me to build my own class.
For instance:
Public Class GPIBInst
Implements Ivi.Visa.Interop.FormattedIO488
Public Address As Integer
Public Sub setAddress(ByVal Addr As Integer)
Address = Addr
End Sub
Public Function getAddress() As Integer
Return Address
End Function
Public Function readIO() As String
Dim Data As String = me.ReadString()
Dim Result As String = mid(Data,2,7)
Return Result
End Function
End Class
This would allow me to use the functions from the interface, but also customize the instruments for other useful things inside the program. For instance, the GPIBInst.Address needs to be used in other places, and the GPIBInst.readIO() can be used instead of just the generic ReadString() so that I can customize the output a little.
BUT when I try to do this, I can't inherit from the interface (because it's an interface) and I can't implement the interface because it says my class needs to implement every single function which the interface provides. I don't want all these functions, and also, I can't work out how to write them all into my class anyway (they have heaps of random stuff in them which I don't understand lol).
If anyone can see where I'm coming from and can offer some advice, I'd really appreciate it =)
An interface is supposed to represent a coherent set of functionality; implementing part of it but not all of it violates the intent of the concept. That being said, it is very common for APIs in object-oriented languages that wrap non-OO systems to just define one massive interface rather than breaking the functionality into logical sub-groups and defining an interface for each group. If that is your circumstance, and you want to implement the interface, you have no choice but to implement every method from the interface (although you can throw a NotImplementException for any method that you don't want to fully implement, as long as that will not prevent your class from functioning properly).

VB.NET EF - Creating a generic function that inspects an entity & permits entity save? Code First

I know, this sounds strange... But this is what I'm trying to do, how far along I am, and why I'm even doing it in the first place:
The class is configured, as an instance, with the name of the class. The context class is also available for preparing the batch class.
Pass a generic list of objects (entities, really) to a class.
That class (which can be pre-configured for this particular class) does just one thing: Adds a new entity to the backend database via DBContext.
The same class can be used for any entity described in the Context class, but each instance of the class is for just one entity class.
I want to write a blog article on my blog showing the performance of dynamically adjusting the batch size when working with EF persistence, and how constantly looking for the optimum batch size can be done.
When I say "DBContext" class, I mean a class similar to this:
Public Class CarContext
Inherits DbContext
Public Sub New()
MyBase.New("name=vASASysContext")
End Sub
Public Property Cars As DbSet(Of Car)
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
modelBuilder.Configurations.Add(Of Car)(New CarConfiguration())
End Sub
End Class
That may sound confusing. Here is a use-case (sorta):
Need: I need to add a bunch of entities to a database. Let's call them cars, for lack of an easier example. Each entity is an instantiation of a car class, which is configured via Code First EF6 to be manipulated like any other class that is well defined in DBContext. Just like in real world classes, not all attributes are mapped to a database column.
High Level:
-I throw all the entities into a generic list, the kind of list supported by our 'batch class'.
-I create an instance of our batch class, and configure it to know that it is going to be dealing with car entities. Perhaps I even pass the context class that has the line:
-Once the batch class is ready (may only need the dbcontext instance and the name of the entity), if is given the list of entities via a function something like:
Public Function AddToDatabase(TheList as List(Of T)) As Double
The idea is pretty simple. My batch class is set to add these cars to the database, and will add the cars in the list it was given. The same rules apply to adding the entities in batch as they do when adding via DBContext normally.
All I want to happen is that the batch class itself does not need to be customized for each entity type it would deal with. Configuration is fine, but not customization.
OK... But WHY?
Adding entities via a list is easy. The secret sauce is the batch class itself. I've already written all the logic that determines the rate at which the entities are added (in something akin to "Entities per Second). It also keeps track of the best performance, and varies the batch size occasionally to verify.
The reason the function above (called AddToDatabase() for illustrative purposes) returns a double is that the double represents the amount of entities that were added per second.
Ultimately, the batch class returns to the calling method the number of entities to put in the next batch to maintain peak performance.
So my question for you all is how I can determine the entity fields, and use that to save the entities in a given list.
Can it be as simple as copying the entities? Do I even need to use reflection at all, and have the class use 'GetType' to figure out the entity class in the list (cars)?
How would you go about this?
Thank yu very much in advance for your reading this far, and your thoughtful response..
[Don't read further unless you are into this kind of thing!]
The performance of a database operation isn't linear, and is dependent on several factors (memory, CPU load, DB connectivity, etc.), and the DB is not always on the same machine as the application. It may even involve web services.
Your first instinct is to say that more entities in a single batch is best, but that is probably not true in most cases. When you add entities to a batch add, at first you see an increase in performance (increase in entities/second). But as the batch size increases, the performance may reach a maximum, then start to decrease (for a lot of reasons, not excluding environmental, such as memory). For non-memory issues, the batch performance may start to level off, and we haven't even discussed the impact of the batch on the system itself.
So in the case of a leveling off, I don't want my batch size any larger than it needs to be to be in the neighborhood of peak performance. Also, with smaller batch sizes, the class is able to evaluate the system's performance more frequently.
Being new to Code First and EF6, I can see that there must be some way to use reflection to determine how to take the given list of entities, break them apart into the entity attributes, and persist them via the EF itself.
So far, I do it this way because I need to manually configure each parameter in the INSERT INTO...
For Each d In TheList
s = "INSERT INTO BDTest (StartAddress, NumAddresses, LastAddress, Duration) VALUES (#StartAddress, #NumAddresses, #LastAddress, #Duration)"
Using cmd As SqlCommand = New SqlCommand(s, conn)
conn.Open()
cmd.Parameters.Add("#StartAddress", Data.SqlDbType.NVarChar).Value = d.StartIP
cmd.Parameters.Add("#NumAddresses", Data.SqlDbType.Int).Value = d.NumAddies
cmd.Parameters.Add("#LastAddress", Data.SqlDbType.NVarChar).Value = d.LastAddie
singleRate = CDbl(Me.TicksPerSecond / swSingle.Elapsed.Ticks)
cmd.Parameters.Add("#Duration", Data.SqlDbType.Int).Value = singleRate
cmd.ExecuteNonQuery()
conn.Close()
End Using
Next
I need to steer away in this test code from using SQL, and closer toward EF6...
What are your thoughts?
TIA!
So, there are two issues I see that you should tackle. First is your question about creating a "generic" method to add a list of entities to the database.
Public Function AddToDatabase(TheList as List(Of T)) As Double
If you are using POCO entities, then I would suggest you create an abstract base class or interface for all entity classes to inherit from/implement. I'll go with IEntity.
Public Interface IEntity
End Interface
So your Car class would be:
Public Class Car
Implements IEntity
' all your class properties here
End Class
That would handle the generic issue.
The second issue is one of batch inserts. A possible implementation of your method could be as follows. This will insert a batches of 100, modify the paramater inputs as needed. Also replace MyDbContext with the actual Type of your DbContext.
Public Function AddToDatabase(ByVal entities as List(Of IEntity)) As Double
Using scope As New TransactionScope
Dim context As MyDbContext
Try
context = new MyDbContext()
context.Configuration.AutoDetectChangesEnabled = false
Dim count = 0
For Each entityToInsert In entities
count += 1
context = AddToContext(context, entityToInsert, count, 100, true)
Next
context.SaveChanges()
Finally
If context IsNot Nothing
context.Dispose()
End If
End Try
scope.Complete()
End Using
End Function
Private Function AddToContext(ByVal context As MyDbContext, ByVal entity As IEntity, ByVal count As Integer, ByVal commitCount As Integer, ByVal recreateContext as Boolean) As MyDbContext
context.Set(entity.GetType).Add(entity)
If (count % commitCount = 0)
context.SaveChanges()
If (recreateContext)
context.Dispose()
context = new MyDbContext()
context.Configuration.AutoDetectChangesEnabled = false
End If
End If
return context
End Function
Also, please apologize if this is not 100% perfect as I mentally converted it from C# to VB.Net while typing. It should be very close.

Interfaces and hungarian notation

Please have a look at the following question: What's the naming convention for classes in the DataAccess Project?
JDK talks about using Namespaces to separate the Data Logic Layer and the Business Logic Layer and not to use Hungarian notation to name interfaces e.g. IPersonDAL for the data access layer. I have followed the recommendations of this answerer in the code below:
Imports com.app.BusinessLogicLayer.Interfaces
Imports com.app.DataLogicLayer.Interfaces
Namespace BusinessLogicLayer
Public Class Order
Implements com.app.BusinessLogicLayer.Interfaces.IOrder
Public Sub Insert()
Dim IOrder As com.app.DataLogicLayer.Interfaces.IOrder = New com.app.DataLogicLayer.Order
End Sub
End Class
End Namespace
Namespace DataLogicLayer
Public Class Order
Public Sub Insert()
End Sub
End Class
End Namespace
Namespace BusinessLogicLayer.Interfaces
Public Interface IOrder
End Interface
End Namespace
Namespace DataLogicLayer.Interfaces
Public Interface IOrder
End Interface
End Namespace
Classes in the business logic layer e.g. Order implement interfaces (IOrder from Business Logic Layer) and use interfaces (IOrder from Data Logic Layer) i.e. the presentation layer communicates with the Business Logic Layer and the Business Logic Layer communicates with the data logic layer with interfaces. Notice that because of this reason; interfaces have to be fully qualified with the namespace. For this reason; isn't it better to name interfaces using hungarian notation e.g. IPersonBLL and IPersonDAL or am I missing something?
Well, this is a subjective topic, but here goes...
Firstly, avoid abbreviations like DAL. Code Analysis yells about acronyms and abbreviations; you're supposed to write it out. In my experience it's wise advise. Opening up ancient code that's full of abbreviations causes a lot of unnecessary WTF moments (pun intended).
Even when spelling things out, when you have 50 classes sitting in your BusinessLogic folder like this:
Company.Product.BusinessLogic
PersonEntity
OrderEntity
MaterialEntity
EmployeeEntity
CustomerEntity
etc.
My gut tells me it's time to refactor. I feel it's better to move the Entity tag to the namespace, so you have this:
Company.Product.BusinessLogic.Entity
Person
Order
Material
Employee
Customer
etc.
Same things applies to interfaces.
This also makes it easier to refactor. If I want to start calling my Entities "BusinessObjects", I just have to rename the namespace, not the class names and file names.
It can be a pain to qualify your class names, but you normally only have to specify the parent namespace, not fully-qualify them. Resharper -> Cleanup Code does wonders here.
In summary, I would not add Hungarian notation to my interface/class name just to make references easier to deal with.
Update: Example
Data Access Layer:
Namespace Company.Product.DataAccess.Adapter
Public Class Product
End Class
End Namespace
Business Layer:
Imports Company.Product.DataAccess
Namespace Company.Product.BusinessLogic.Entity
Public Class Product
Dim adapter As New Adapter.Product()
End Class
End Namespace
User Interface (ideally your UI should only interact with the business layer, never with the data layer directly):
Imports Company.Product.BusinessLogic
Namespace Company.Product.UserInterface.Webpage
Public Class Product
Dim productEntity As New Entity.Product()
End Class
End Namespace
Notice that because of this reason; interfaces have to be fully qualified with the namespace. For this reason; isn't it better to name interfaces using hungarian notation e.g. IPersonBLL and IPersonDAL or am I missing something?
I see what you are saying, but I don't understand why fully-qualifying the names is bad or why it would be "better" to name the interfaces using "Hungarian" notation. (And I say this as a truly unrepentant fan of Simonyi's apps Hungarian.)
Remember that regardless of the names and locations of the classes/interfaces, the compiler is going to produce the same object code. The apparent nesting level is not going to "slow down" your code to any perceptible degree.
If it really bothers you to type out the names (and Intellisense is of no consolation), you can always use something like a namespace alias with a using directive. But I'd be careful with overusing theseā€”I think it makes the code even harder to read.

Dependency injection of local variable returned from method

I'm (somewhat) new to DI and am trying to understand how/why it's used in the codebase I am maintaining. I have found a series of classes that map data from stored procedure calls to domain objects. For example:
Public Sub New(domainFactory As IDomainFactory)
_domainFactory = domainFactory
End Sub
Protected Overrides Function MapFromRow(row As DataRow) As ISomeDomainObject
Dim domainObject = _domainFactory.CreateSomeDomainObject()
' Populate the object
domainObject.ID = CType(row("id"), Integer)
domainObject.StartDate = CType(row("date"), Date)
domainObject.Active = CType(row("enabled"), Boolean)
Return domainObject
End Function
The IDomainFactory is injected with Spring.Net. It's implementation simply has a series of methods that return new instances of the various domain objects. eg:
Public Function CreateSomeDomainObject() As ISomeDomainObject
Return New SomeDomainObject()
End Function
All of the above code strikes me as worse than useless. It's hard to follow and does nothing of value. Additionally, as far as I can tell it's a misuse of DI as it's not really intended for local variables. Furthermore, we don't need more than one implementation of the domain objects, we don't do any unit testing and if we did we still wouldn't mock the domain objects. As you can see from the above code, any changes to the domain object would be the result of changes to the SP, which would mean the MapFromRow method would have to be edited anyway.
That said, should I rip this nonsense out or is it doing something amazingly awesome and I'm missing it?
The idea behind dependency injection is to make a class (or another piece of code) independent on a specific implementation of an interface. The class outlined above does not know which class implements IDomainFactory. A concrete implementation is injected through its constructor and later used by the method MapFromRow. The domain factory returns an implementation of ISomeDomainObject which is also unknown.
This allows you supplement another implementation of these interfaces without having to change the class shown above. This is very practical for unit tests. Let's assume that you have an interface IDatabase that defines a method GetCustomerByID. It is difficult to test code that uses this method, since it depends on specific customer records in the database. Now you can inject a dummy database class that returns customers generated by code that does not access a physical database. Such a dummy class is often called a mock object.
See Dependency injection on Wikipedia.

VB.NET - I'm Refactoring and Could Use Some Help

I'm working with vb.net, wcf, wpf and I'm refactoring working code with the hope of being able to reduce some amount of redundancy. I have a bunch of methods that get called in several places throughout the code that only have a slight variation from each other and I would like to replace them with a single method instead.
Specifically, each of the redundant methods process an 1-d array that contain different objects I have created. There are several of these different object types each with different signatures but they have all have a "name" and "Id" property. (Also these objects don't have a shared base class but I could add that if needed.) Each of the redundant methods deal with a different one of the object types.
To refactor the code I would like to pass any of the different object arrays to a single new method that could access the "name" and "id" properties. I'm trying to write this new method in a fashion that wouldn't require me to update it if I created more objects down the road.
I've done some reading on Delegates and Generic Classes but I can't really figure out how this fits in. It would almost be as if I wanted to create a generic class that could handle each of my object types but then somehow also access the "name" and "id" propeties of the different object types.
Any help you can provide would be appretiated. Also, please keep in mind this project is written in VB.net.
Thanks
Mike
It sounds like having your object implement a common interface or have a shared base class would be best. Interfaces give you the most flexibility down the road if you ever need to pass a class to this method that must derive from some other class that does not implement the interface. However, a base class that implements the interface may also be useful just to reduce the duplicate declarations of these properties.
Public Interface IThingThatHasNameAndId 'good name not included
ReadOnly Property Name As String
ReadOnly Property Id As Integer
End Interface
Once you have the interface, you can then pass arrays of types implementing the interface as IEnumerable(Of IThingThatHasNameAndId) or make a generic method taking T() and constrain T to the interface.
Make a base class with the Name and ID properties, then you can make a method that takes in any class that derrives from that class.
Public Function TestFunction(Of t As YourBaseClass)(Byval obj As t) As Boolean
If obj.Name = "Some Name" AndAlso obj.ID = 1 Then
Return True
Else
Return False
End If
End Function