Deserialize Object inside object - vb.net

Is this possible?
Public Class Foo
public var as string
public sub Load(byval filename as string)
'This is done
[...]
oItem = [...] 'Code to deserialize
me = oItem 'THIS LINE
end sub
end class
So that you can load foo from the serialized file like so:
Public Sub Main
Dim f as Foo = new Foo()
f.load("myFile")
end sub
Up until now i've had a function that that returns Foo as Object (I'm trying to make the serialize / deserialize process general so I can just copy and paste and avoid explicitly setting each variable)

No, what you want to do in your case is have Load be a Shared Function that returns the newly created item.
More like:
Public Class Foo
public var as string
public Shared Function Load(byval filename as string) As Foo
'This is done
[...]
oItem = [...] 'Code to deserialize
Return oItem
end sub
end class
Public Sub Main
Dim f as Foo
f = Foo.load("myFile")
end sub
Also, rather than embedding the deserialization directly into each class, you can have a general purpose method, such as:
''' <summary>
''' This method is used to deserialize an object from a file that was serialized using the SoapFormatter
''' </summary>
''' <param name="sFileName"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function Deserialize(Of T)(ByVal sFileName As String) As T
' Exceptions are handled by the caller
Using oStream As Stream = File.Open(sFileName, FileMode.Open, IO.FileAccess.Read)
If oStream IsNot Nothing Then
Return DirectCast((New SoapFormatter).Deserialize(oStream), T)
End If
End Using
Return Nothing
End Function
which you can then call as:
Public Sub Main
Dim f as Foo
f = Deserialize(Of Foo)("myFile")
end sub

Related

Method Call from ASP to .NET COM fails

Background:
I have a legacy application written in ASP (VBScript) which call COM components written in VB6. We are upgrading in phases and need to first update COM components to .NET while maintaining interoperability with ASP.
Situation:
I created a sample .NET class and exposed it to COM system using various attributes as per MSDN documentation
I am able to instantiate the class
I am able to call the desired method on the class
Problem:
Argument values are not being sent to COM method. e.g. all numeric types have value 0 inside the method; all reference types have null value inside the method. Literal strings are passed properly to the method. However, string variables are not passed.
Same issue with return value. Regardless of value returned by the method, the variable on ASP has default value (0 or null as the case may be).
COM Code
<ComVisible(True)>
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
Public Interface IClass1
Function Triple(ByVal input As String) As Integer
End Interface
<ComVisible(True)>
<ProgId("TESTCOM.Class1")>
<ClassInterface(ClassInterfaceType.None)>
Public Class Class1
Inherits ServicedComponent
Implements IClass1
Public Sub New()
' needed for COM
End Sub
Public Function Triple(input As String) As Integer Implements IClass1.Triple
IO.File.WriteAllText("C:\TestCOM.Class1_Triple.log", String.Format("[{0:s}] Input: {1}", Date.Now, input)) ''' this file is updated; so I know method is being called.
Return 97
End Function
End Class
Alternate COM Code
<ComVisible(True)>
<ProgId("TESTCOM.Class1")>
<ComClass("E26FE8A0-8AC7-4824-9776-30ECDD473AA3")>
Public Class Class1
'Inherits ServicedComponent
'Implements IClass1
Public Sub New()
' needed for COM
End Sub
Private Const LogMessageFormat As String = "[{0:s}] Input: {1}, {2}" + vbCrLf
Public Function Triple(csinput As String, nInput As Integer) As Integer 'Implements IClass1.Triple
IO.File.AppendAllText("C:\TestCOM.Class1_Triple.log",
String.Format(LogMessageFormat, Date.Now, if(csinput isnot Nothing, csinput, "**NULL**"), nInput))
Return 97
End Function
End Class
ASP Code
dim testNETCOM
set testNETCOM = Server.CreateObject("TESTCOM.Class1")
' ** use this to check if there was any error during instantiation
If Err.Number <> 0 Then
Response.Redirect("http://"&Err.Description&"/")
'Response.Write (Err.Description& "<br><br>")
else
'Response.Redirect("http://no-error/")
End If
' ** use this to check if object is actually instantiated
if testNETCOM is nothing then
Response.Redirect("http://no-com/")
else
'Response.Redirect("http://yes-com/")
end if
dim nInput
set nInput = 41
dim nOutput
set nOutput = -1
set nOutput = CLng(testNETCOM.Triple("test message")) ' this string is received in the method
set nOutput = CLng(testNETCOM.Triple(CStr(nInput))) ' this string is not received in the method
' ** use this to check if return value is what we expected
if nOutput <> 0 then
Response.Redirect("http://test/")
else
Response.Redirect("http://notest/") ''' **this happens**
end if
The issue is in the syntax on ASP
For simple data types, do not use 'set'
For objects, use 'set'
Because I was using set for simple types, there was an error during the assignment process and the value of the variable for null/nothing/empty.
set nInput = 41 ' this is wrong
nInput = 41 ' this is right
set nOutput = CLng(testNETCOM.Triple(CStr(nInput))) ' this is wrong
nOutput = CLng(testNETCOM.Triple(CStr(nInput))) ' this is right
Give either of these a try:
<ComVisible(True)>
<Guid("79571A9D-2345-48D9-8F86-7F6761A97DBA")>
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
Public Interface IClass1
Function Triple(ByVal input As String) As Integer
End Interface
<ComVisible(True)>
<Guid("E26FE8A0-8AC7-4824-9776-30ECDD473AA3")>
<ProgId("TESTCOM.Class1")>
<ClassInterface(ClassInterfaceType.None)>
Public Class Class1
Inherits ServicedComponent
Implements IClass1
Public Sub New()
' needed for COM
End Sub
Public Function Triple(input As String) As Integer Implements IClass1.Triple
IO.File.WriteAllText("C:\TestCOM.Class1_Triple.log", String.Format("[{0:s}] Input: {1}", Date.Now, input)) ''' this file is updated; so I know method is being called.
Return 97
End Function
End Class
Or:
<ComVisible(True)>
<ProgId("TESTCOM.Class1")>
<ComClass("E26FE8A0-8AC7-4824-9776-30ECDD473AA3", "79571A9D-2345-48D9-8F86-7F6761A97DBA")>
Public Class Class1
'Inherits ServicedComponent
'Implements IClass1
Public Sub New()
' needed for COM
End Sub
Private Const LogMessageFormat As String = "[{0:s}] Input: {1}, {2}" + vbCrLf
Public Function Triple(csinput As String, nInput As Integer) As Integer 'Implements IClass1.Triple
IO.File.AppendAllText("C:\TestCOM.Class1_Triple.log",
String.Format(LogMessageFormat, Date.Now, if(csinput isnot Nothing, csinput, "**NULL**"), nInput))
Return 97
End Function
End Class

Returning object instead of string and integer

I'm working on a vb.net project where a user can save and open a binary text.
However, the problem is that the when opening a file, it returns a object instead of string and integer.
It returns Projectname.Classname
What I want it to return is name and age that the user entered when saving the file.
Here is my code:
''' <summary>
''' When the user clicks open
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub OpenToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OpenToolStripMenuItem.Click
Try
If (openFileDialog1.ShowDialog = DialogResult.OK) Then
thefilename = openFileDialog1.FileName
Dim message = animalmgr.ReadFile(thefilename)
'Getting method from manager
If (Not (message) Is Nothing) Then
message.ToList().ForEach(Sub(msg) Resultlst.Items.Add(msg))
Else
UpdateResults()
End If
End If
Catch ex As Exception
MessageBox.Show(ex.ToString, "Error in opening file")
End Try
End Sub
ReadFile function in the manager class:
''' <summary>
''' Reads a file from binary
''' </summary>
''' <param name="filename"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function ReadFile(ByVal filename As String) As Animal()
Dim BinSerial As BinSerializerUtility = New BinSerializerUtility
Dim animals = BinSerial.BinaryFileDeSerialize(Of Animal)(filename)
Return animals.ToArray
End Function
I did the exact same project in C# which worked perfectly, I don't know why it doesn't work in vb.net however. Does anyone know the problem and how to solve it?
Update:
Class BinSerializerUtility
Public Class BinSerializerUtility
Public Sub BinaryFileSerialize(ByVal objs As List(Of Animal), ByVal filePath As String)
Dim fileStream As FileStream = Nothing
Try
fileStream = New FileStream(filePath, FileMode.Create)
Dim b As BinaryFormatter = New BinaryFormatter
For Each obj In objs
b.Serialize(fileStream, obj)
Next
Finally
If (Not (fileStream) Is Nothing) Then
fileStream.Close()
End If
End Try
End Sub
Public Function BinaryFileDeSerialize(Of T As {Class})(ByVal filePath As String) As List(Of T)
Dim list = New List(Of T)
If Not File.Exists(filePath) Then
Throw New FileNotFoundException(("The file" + " was not found. "), filePath)
End If
Dim fileStream = New FileStream(filePath, FileMode.Open)
Dim b As BinaryFormatter = New BinaryFormatter
While (fileStream.Position < fileStream.Length)
list.Add(CType(b.Deserialize(fileStream), T))
End While
Return list
End Function
End Class
Animal class:
<Serializable()>
Public MustInherit Class Animal
Implements IAnimal
Private theCatagorytype As Categorytype
Private m_name As String
Private m_age As Integer
Private m_gender As String
Private m_id As Integer
Public Sub New(ByVal typ As Categorytype)
MyBase.New()
theCatagorytype = typ
End Sub
Public Sub New()
MyBase.New()
End Sub
#Region "Properties"
Public Overridable ReadOnly Property Description As String
Get
Return String.Format("{0}, {1}, {2}, {3}", Me.Id, Me.Name, Me.Age, Me.Gender)
End Get
End Property
Public Property Categorytype As Categorytype
Get
Return theCatagorytype
End Get
Set(value As Categorytype)
theCatagorytype = value
End Set
End Property
Public Property Id As Integer Implements IAnimal.Id
Get
Return m_id
End Get
Set(value As Integer)
If (value > 0) Then
m_id = value
End If
End Set
End Property
Public Property Name As String Implements IAnimal.Name
Get
Return m_name
End Get
Set(value As String)
m_name = value
End Set
End Property
Public Property Age As Integer
Get
Return m_age
End Get
Set(value As Integer)
m_age = value
End Set
End Property
Public Property Gender As String Implements IAnimal.Gender
Get
Return m_gender
End Get
Set(value As String)
m_gender = value
End Set
End Property
#End Region
Public MustOverride Function GetEaterType() As EaterType Implements IAnimal.GetEaterType
Public MustOverride Function GetSpecies() As String Implements IAnimal.GetSpecies
End Class
Rather than writing a class wrapper for an operation, I think it makes more sense to put such Save and Load functions in the class itself:
' in Animal class:
Friend Shared Function LoadData(myFile As String) As List(Of Animal)
Dim newList As List(Of Animal)
If File.Exists(myFile) Then
Using fs As New FileStream(myFile, FileMode.Open)
Dim bf = New BinaryFormatter
newList = CType(bf.Deserialize(fs), List(Of Animal))
End Using
Else
'return empty list of there is no file
newList = New List(Of Animal)
End If
Return newList
End Function
This seems simpler than trying to read one object at a time and place it in a List. Organizationally, it makes for fewer utility classes if the Foos, Bars and Animals can all serialize and deserialize themselves. To load them:
animals = Animal.LoadData(FileName)
' put animals in a ListBox:
myfrm.ListBox1.Items.AddRange(animals.ToArray)
Even better than making a copy of the animals for the list box, is to use your List(Of Animal) as the DataSource. That way, the user sees the same data set as your code is using.
When adding objects to a listbox or dropdown list, by default it uses ToString() to give you a string representation of the object, and the class name is the default ToString() implementation.
If you override ToString() in your Animal class, it will display however you need it to.
EDIT This is assuming you really want your ReadFile method to return a collection of Animal objects, and you want to add the actual objects to the listbox instead of truly adding string representations to the listbox.

Serialize an object that contains a list of objects

I'v build a NotInheritable Serilizer that serilizes all my classes and list of classes with success.
Until I'v build a list of class that contains a list of classes.
I'm getting the runtime Exeption: There was an error generating the XML document. resulting in a perfectly empty XML :(
These are my classes to serilize:
<System.Serializable> _
<System.Xml.Serialization.XmlInclude(GetType(StatisticItem))> _
Public Class Statistic
Public StatItem As New list(Of StatisticItem)
'Bla bla bla
end class
<Serializable> _
Public Class StatisticItem
Private stStatPath As String = ""
Private eStatType As StatType = 0
Private iBatchNumber As Int32 = 0
end class
And the serializer:
Public NotInheritable Class XmlSerializer
Public Shared Sub Serialize(Of T)(ByVal obj As T, sConfigFilePath As String)
Dim XmlBuddy As New System.Xml.Serialization.XmlSerializer(GetType(T))
Dim MySettings As New System.Xml.XmlWriterSettings()
MySettings.Indent = True
MySettings.CloseOutput = True
Dim MyWriter As System.Xml.XmlWriter=System.Xml.XmlWriter.Create(sConfigFilePath,MySettings)
XmlBuddy.Serialize(MyWriter,obj)
MyWriter.Flush()
MyWriter.Close()
' ----- OLD CODE FOR SERIALIZE, NEXTLINE IN XML DOESNT WORK ON WIN CE -------,
' B.T.W. Using This code to serilize gives the exact same fault
'Dim XmlBuddy As New System.Xml.Serialization.XmlSerializer(GetType(T))
'Dim objStreamWriter As New StreamWriter(sConfigFilePath)
'XmlBuddy.Serialize(objStreamWriter, obj)
'objStreamWriter.Close()
End Sub
end class
And this is the call:
XmlSerializer.Serialize(Of list(Of Statistic))(StatCollection, CommCtrl.PathStatisticFile)
If i comment the list in StatisticItem everything works.
I think if I Implement IXmlSerializable in StatisticItem I can tell the serializer how to work to make it work, but I see other code example on the internet where this works without all this effort
and I prefer a clean solution, that is about the same as all my other classes.
Hope one of you guys can help me out
Yes solved!, To be honest I changed so much small things that I still don't know what the cause was.
Maybe that there were still some private members.
Anyway, maybe the code can be useful for anyone:
Public Class Statistic
'Properties
Private eStatName As String
Private eStatSort As StatSort
Private StatItem As New list(Of StatisticItem)
Public Property Name() As String
Get
Return eStatName
End Get
Set(ByVal value As String)
eStatName = value
End Set
End Property
'Other public properties
End class
Public Class StatisticItem
Private stStatPath As String = ""
Private eStatType As StatType = 0
Private iBatchNumber As Int32 = 0
Public Property Path() As String
Get
Return stStatPath
End Get
Set(ByVal Value As String)
stStatPath = Value
End Set
End Property
' The other Public Properties
Serializer:
Public NotInheritable Class XmlSerializer
''' <summary>
''' Convert a class state into XML
''' </summary>
''' <typeparam name="T">The type of object</typeparam>
''' <param name="obj">The object to serilize</param>
''' <param name="sConfigFilePath">The path to the XML</param>
Public Shared Sub Serialize(Of T)(ByVal obj As T, sConfigFilePath As String)
Dim XmlBuddy As New System.Xml.Serialization.XmlSerializer(GetType(T))
Dim MySettings As New System.Xml.XmlWriterSettings()
MySettings.Indent = True
MySettings.CloseOutput = True
Dim MyWriter As System.Xml.XmlWriter = System.Xml.XmlWriter.Create(sConfigFilePath,MySettings)
XmlBuddy.Serialize(MyWriter,obj)
MyWriter.Flush()
MyWriter.Close()
End Sub
''' <summary>
''' Restore a class state from XML
''' </summary>
''' <typeparam name="T">The type of object</typeparam>
''' <param name="xml">the path to the XML</param>
''' <returns>The object to return</returns>
Public Shared Function Deserialize(Of T)(ByVal xml As String) As T
Dim XmlBuddy As New System.Xml.Serialization.XmlSerializer(GetType(T))
Dim fs As New FileStream(xml, FileMode.Open)
Dim reader As New Xml.XmlTextReader(fs)
If XmlBuddy.CanDeserialize(reader) Then
Dim tempObject As Object = DirectCast(XmlBuddy.Deserialize(reader), T)
reader.Close()
Return tempObject
Else
Return Nothing
End If
End Function
end class
The call of the Serializer:
Try
XmlSerializer.Serialize(Of list(Of Statistic))(StatCollection, CommCtrl.PathStatisticFile)
Catch ex As Exception
msgbox(ex.Message)
End Try
The call of the deSerializer:
Try
StatCollection = XmlSerializer.Deserialize(Of list(Of Statistic)(CommCtrl.PathStatisticFile)
Catch ex As Exception
msgbox(ex.Message)
end Try
I needed to do this also but create a string instead. Here's my solution:
Public Shared Function Serialize(Of T)(ByVal obj As T) As String
Dim xml As New System.Xml.Serialization.XmlSerializer(GetType(T))
Dim ns As New System.Xml.Serialization.XmlSerializerNamespaces()
ns.Add("", "") 'No namespaces needed.
Dim sw As New IO.StringWriter()
xml.Serialize(sw, obj, ns)
If sw IsNot Nothing Then
Return sw.ToString()
Else
Return ""
End If
End Function
Public Shared Function Deserialize(Of T)(ByVal serializedXml As String) As T
Dim xml As New System.Xml.Serialization.XmlSerializer(GetType(T))
Dim sr As New IO.StringReader(serializedXml)
Dim obj As T = CType(xml.Deserialize(sr), T)
Return obj
End Function

VB.NET: Get dynamically value of constants

If have got the following definitions of constants:
Protected Const Xsl As String = "Configuration.Xsl"
Protected Const Form As String = "Settings.Form"
Protected Const Ascx As String = "Implementation.Ascx"
...
To fill a dictionary I use this constants as keys:
MyDictionary.Add(Converter.Xsl, "Item 1")
MyDictionary.Add(Converter.Form, "Item 2")
MyDictionary.Add(Converter.Ascx, "Item 3")
...
Now I run throug a loop of XML files and extract the name of the root node:
Dim document As New XmlDocument
document.Load(File.FullName)
Dim rootName As String = document.DocumentElement.Name
The root name matchs with the name of the constant. To get the value of an item from the dictionary I can use something like this:
Select Case rootName.ToUpper
Case "Xsl".ToUpper
DictionaryValue = MyDictionary(Class.Xsl)
Case "Form".ToUpper
DictionaryValue = MyDictionary(Class.Form)
Case "Ascx".ToUpper
DictionaryValue = MyDictionary(Class.Ascx)
...
Case Else
End Select
If a constant is added or removed I also have to change the selection. Is there another way to get the value of a constant? Something like
DictionaryValue = MyDictionary(SomeFunctionToGetConstantValue(rootName))
Thanks for any response.
Try this:
For Each sKey As String In MyDictionary.Keys
If rootName.Equals(sKey, StringComparison.CurrentCultureIgnoreCase) Then
DictionaryValue = MyDictionary(sKey)
Exit For
End If
Next
At least it will reduce the amount of coding in the select case.
#Clara Onager
My solution I used was the following
Me.GetType.GetField(
"Xsl",
Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Static Or System.Reflection.BindingFlags.FlattenHierarchy
).GetValue(Nothing)
This is a bit of a whopper but I think it provides a pretty elegant solution overall. This is how it is used:
Public Class ConstantsExample
Public Sub UseConstant()
Dim value As String = Constants.Types(TypeA)
Dim category As String = Constants.Categories(General)
End Sub
End Class
As you can see the code where you use it is as short as it can be made. It does rely on a big pile of source code though:
Public Enum TypeCodes
<Description("Type A")> TypeA = 0
<Description("Type B")> TypeB
<Description("Type C")> TypeC
End Enum
Public Enum CategoryCodes
<Description("General")> General = 0
<Description("Specific")> Specific
<Description("Other")> Other
End Enum
Public NotInheritable Class Constants
#Region "Resources"
Private Shared myTypes As Dictionary(Of TypeCodes, ConstantItem) = Nothing
Public Shared ReadOnly Property Types() As Dictionary(Of TypeCodes, ConstantItem)
Get
If myTypes Is Nothing Then
myTypes = New Dictionary(Of TypeCodes, ConstantItem)
BuildTypes(myTypes)
End If
Return myTypes
End Get
End Property
Private Shared Sub BuildTypes(ByRef dict As Dictionary(Of TypeCodes, ConstantItem))
With dict
.Add(TypeCodes.TypeA, New ConstantItem(TypeCodes.TypeA.Description, "Type A are..."))
.Add(TypeCodes.TypeB, New ConstantItem(TypeCodes.TypeB.Description, "Type B are..."))
.Add(TypeCodes.TypeC, New ConstantItem(TypeCodes.TypeC.Description, "Type C are..."))
End With
End Sub
#End Region
#Region "Categories"
Private Shared myCategories As Dictionary(Of CategoryCodes, ConstantItem) = Nothing
Public Shared ReadOnly Property Categories() As Dictionary(Of CategoryCodes, ConstantItem)
Get
If myCategories Is Nothing Then
myCategories = New Dictionary(Of CategoryCodes, ConstantItem)
BuildCategories(myCategories)
End If
Return myCategories
End Get
End Property
Private Shared Sub BuildCategories(ByRef dict As Dictionary(Of CategoryCodes, ConstantItem))
With dict
.Add(CategoryCodes.General, New ConstantItem(CategoryCodes.General.Description, "General category"))
.Add(CategoryCodes.Specific, New ConstantItem(CategoryCodes.Specific.Description, "Specific category"))
.Add(CategoryCodes.Other, New ConstantItem(CategoryCodes.Other.Description, "Other category"))
End With
End Sub
#End Region
End Class
Public NotInheritable Class ConstantItem
#Region "Constructors"
''' <summary>
''' Default constructor.
''' </summary>
Public Sub New()
'Do nothing
End Sub
''' <summary>
''' Simple constructor.
''' </summary>
Sub New(value As String)
Me.Name = value
Me.Description = value
End Sub
''' <summary>
''' Proper constructor.
''' </summary>
Sub New(name As String, description As String)
Me.Name = name
Me.Description = description
End Sub
#End Region
Property Name As String
Property Description As String
''' <summary>
''' See http://stackoverflow.com/questions/293215/default-properties-in-vb-net
''' </summary>
Public Shared Widening Operator CType(value As String) As ConstantItem
Return New ConstantItem(value)
End Operator
''' <summary>
''' See http://stackoverflow.com/questions/293215/default-properties-in-vb-net
''' </summary>
Public Shared Widening Operator CType(value As ConstantItem) As String
Return value.Name
End Operator
End Class
Note the use of the Widening Operator to dispense with having to type .Item. If you'd rather not use the Widening Operator then simple comment that bit out and change Constants.Types(TypeA) to Constants.Types.Item(TypeA).
This is the Description Extension you may need:
Public Module Extensions
Private Enum SampleDescription
<Description("Item One")> ItemOne = 1
<Description("Item Two")> ItemTwo = 2
<Description("Item Three has a long description")> ItemThree = 3
End Enum
''' <summary>
''' This procedure gets the description attribute of an enum constant, if any. Otherwise it gets
''' the string name of the enum member.
''' </summary>
''' <param name="value"></param>
''' <returns></returns>
''' <remarks>Usage: myenum.Member.Description()
''' Add the Description attribute to each member of the enumeration.</remarks>
<Extension()> _
Public Function Description(ByVal value As [Enum]) As String
Dim fi As Reflection.FieldInfo = value.GetType().GetField(value.ToString())
Dim aattr() As DescriptionAttribute = DirectCast(fi.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
If aattr.Length > 0 Then
Return aattr(0).Description
Else
Return value.ToString()
End If
End Function
End Module
And these are the Imports statements I used (the Assembly is called MyPatterns):
Imports System.ComponentModel
Imports MyPatterns.TypeCodes
Imports MyPatterns.CategoryCodes
Importing the two 'codes' allows you to do without the prefix for the Enum which shortens the code.

ConnectionString In Class Library

I'm merging two of my projects that can share a lot of the same classes into one solution with two web applications and a shared class library.
I've literally just dumped all the classes into the class library project and as expected I've got a ton of errors to fix. My main problem at the moment is the connection string. Currently I have this (which is obviously not going to work):
''' <summary>
''' Initialise the data access layer by loading the database connection string from the Web.Config file
''' </summary>
''' <remarks></remarks>
Shared Sub New()
_connectionString = WebConfigurationManager.ConnectionStrings("ClientFamilyManagementConnectionString").ConnectionString
End
What do I do with my connection strings now the classes are not in a web application?
I really feel like I'm missing something here so below I'm include an example of a class from the BLL and DAL. I can't pass in the connection string to the constructor of the DAL - it says it can't have any parameters.
BLL:
Imports Microsoft.VisualBasic
Imports System.Collections.Generic
Namespace CompanyName
<Serializable()> Public Class SubMarketSector
Private _id As Integer
Private _name As String
Public Property ID() As Integer
Get
Return _id
End Get
Set(ByVal value As Integer)
_id = value
End Set
End Property
Public Property Name() As String
Get
Return _name
End Get
Set(ByVal value As String)
_name = value
End Set
End Property
Public Sub New()
End Sub
Public Shared Function GetAllSubMarketSectors() As List(Of CompanyName.SubMarketSector)
Dim newSubMarketSectorDAO As New SubMarketSectorDAO
Return newSubMarketSectorDAO.GetAllSubMarketSectors
End Function
Public Shared Function GetSubMarketSectorByID(ByVal subMarketSectorID As Integer) As CompanyName.SubMarketSector
Dim newSubMarketSectorDAO As New SubMarketSectorDAO
Return newSubMarketSectorDAO.GetSubMarketSectorByID(subMarketSectorID)
End Function
End Class
End Namespace
DAL:
Namespace CompanyName
Public Class SubMarketSectorDAO
Private Const MainSelectByStatement As String = "SELECT ID, Name FROM Sub_Market_Sectors"
Private Const MainOrderByStatement As String = " ORDER BY Name"
Private Shared ReadOnly _connectionString As String = String.Empty
''' <summary>
''' Initialise the data access layer by loading the database connection string from the Web.Config file
''' </summary>
''' <remarks></remarks>
Shared Sub New()
_connectionString = WebConfigurationManager.ConnectionStrings("PursuitsConnectionString").ConnectionString
End Sub
''' <summary>
''' Returns a List of all Sub Market Sectors
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetAllSubMarketSectors() As List(Of CompanyName.SubMarketSector)
' Create the Connection
Dim currentConnection As SqlConnection = New SqlConnection(_connectionString)
' Create the Command Object, set the CommandText, add any required Parameters and set the Connection
Dim currentCommand As New SqlCommand
currentCommand.CommandText = MainSelectByStatement & MainOrderByStatement
currentCommand.Connection = currentConnection
Dim listOfSubMarketSectors As New List(Of CompanyName.SubMarketSector)
Using currentConnection
' Open the Connection
currentConnection.Open()
' Create the DataReader and Execute the Command
Dim currentDataReader As SqlDataReader = currentCommand.ExecuteReader()
' Populate the list with data
Do While currentDataReader.Read
Dim newSubMarketSector As CompanyName.SubMarketSector = PopulateSubMarketSector(currentDataReader)
listOfSubMarketSectors.Add(newSubMarketSector)
Loop
End Using
Return listOfSubMarketSectors
End Function
''' <summary>
''' Return a single Sub Market Sector
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetSubMarketSectorByID(ByVal subMarketSectorID As Integer) As CompanyName.SubMarketSector
' Create the Connection
Dim currentConnection As SqlConnection = New SqlConnection(_connectionString)
' Create the Command Object, set the CommandText, add any required Parameters and set the Connection
Dim currentCommand As New SqlCommand
currentCommand.CommandText = MainSelectByStatement & " WHERE ID = #subMarketSectorID" & MainOrderByStatement
currentCommand.Parameters.AddWithValue("#subMarketSectorID", subMarketSectorID)
currentCommand.Connection = currentConnection
Dim newSubMarketSector As New CompanyName.SubMarketSector
Using currentConnection
' Open the Connection
currentConnection.Open()
' Create the DataReader and Execute the Command
Dim currentDataReader As SqlDataReader = currentCommand.ExecuteReader()
' Populate the Market Sector
Do While currentDataReader.Read
newSubMarketSector = PopulateSubMarketSector(currentDataReader)
Loop
End Using
Return newSubMarketSector
End Function
Private Function PopulateSubMarketSector(ByVal currentDataReader As SqlDataReader) As CompanyName.SubMarketSector
Dim newSubMarketSector As New CompanyName.SubMarketSector
If Not (currentDataReader.IsDBNull(currentDataReader.GetOrdinal("ID"))) Then
newSubMarketSector.ID = currentDataReader("ID")
End If
If Not (currentDataReader.IsDBNull(currentDataReader.GetOrdinal("Name"))) Then
newSubMarketSector.Name = currentDataReader("Name")
End If
Return newSubMarketSector
End Function
End Class
End Namespace
How about storing the ConnectionStrings in each WebApplication and passing the specific connection string to the class library on instanciation. I don't know how you designed the class library (static methods, singleton, or whatever) but maybe you could pass them (each ConnectionString) to the constructor to set an instance variable which you later use (the same way like before).