Change connection string from class library in main application at run-time - vb.net

You can change the connection string at run-time like this. You make the connection string setting available for writing as a separate property inside the MySettings class:
Partial Friend NotInheritable Class MySettings
Public WriteOnly Property RunTimeConnectionString()
Set(ByVal value)
My.Settings("MyConnectionString") = value
End Set
End Property
End Class
Then, in some place when the application is being initialized (before using any table adapters of typed datasets), write something like:
My.Settings.RunTimeConnectionString = My.Settings.ProductionConnectionString
Where ProductionConnectionString is a simple String setting. It is a User Scope setting so every user can change it (by assigning a value to it, similar to the code above) and save it by calling My.Settings.Save()
This code works well for connection strings which were initially created in the main project and stored in it's settings (= app.config file).
The connection string in the app.config actually has a longer name: MyApp.MySettings.MyConnectionString.
When you have a connection string stored in the app.config in a class library project, and reference that project in the main project, the app.config files will somehow be merged, so the class library has it's settings.
The thing that don't know how to do, is change a setting from the class library at run-time. I could copy the connection string setting from the class library to the main project's app.config. I must keep the same name, which looks something like: MyClassLibrary.My.MySettings.MyConnectionString.
Can the same principle I showed above be somehow applied to this second connection string?

I tested a little more, and found out that the same solution can be used inside a class library.
I made a new class (in the class library) with a shared (static) method like this:
Public Class MySettingsChanger
Public Shared Sub SetConnectionString(ByVal cnnString As String)
My.Settings.RunTimeConnectionString = cnnString
End Sub
End Class
And extended the MySettings class (in the class library) the same way as in the main project:
Namespace My
Partial Friend NotInheritable Class MySettings
Public WriteOnly Property RunTimeConnectionString()
Set(ByVal value)
My.Settings("MyConnectionString") = value
End Set
End Property
End Class
End Namespace
At least it works in my case. The name of the connection in the main project and in the class library is the same only (the short name, not the whole ProjectNamespace.MySettings.ConnectionName). I haven't tested with having a different name of the connection in the class library, but think it should not matter.

I searched more, and found a way, but it isn't really runtime. At least not as runtime as I would like it to be. Anyway, here is the code, I tested it and it worked, but required me to restart the application first. That's not very runtime to me.
Dim configLocation As String = Reflection.Assembly.GetExecutingAssembly().Location
Dim config As Configuration.Configuration = Configuration.ConfigurationManager.OpenExeConfiguration(configLocation)
config.ConnectionStrings.ConnectionStrings.Clear()
For i As Integer = 0 To Configuration.ConfigurationManager.ConnectionStrings.Count - 1
Dim connection As New Configuration.ConnectionStringSettings(Configuration.ConfigurationManager.ConnectionStrings(i).Name, My.Settings.ProductionConnectionString)
connection.ProviderName = Configuration.ConfigurationManager.ConnectionStrings(i).ProviderName
config.ConnectionStrings.ConnectionStrings.Add(connection)
Next
config.Save()
This is the article where I found this code.

Thanks for the message on the blog. Yes, it is hardly run-time as it requires you to stop running for the changes to be picked up. Unfortunately, because settings are loaded once and only once (when the app domain is loaded), there isn't a way for the settings infrastructure to pick up changes while running.
The only option is to either restart the app or recyle the app pool if a web application. Beyond that, you would have to roll your own.
I did the best I could :-)

Related

Vb.Net setting connection in Module

I'm creating a new Vb.Net project and I'm looking to create a module that will fire up when project is run so that the connection is set. I created a new module called Connection and placed the following code there...
Imports System.Data.SqlClient
Module Connection
Sub main()
Dim sConnection As String = "Data Source=Van;Initial Catalog=OP;User ID=userid;Password=password"
End Sub
End Module
And now in my Form1 I added the SQLConnection component and attempt to do something like this....
Using Con as New SQLConnection(sConnection)
'but this does not seem to work. The connection string works properly since it's fully working if I include it in the form itself.
Any particular reason why this is happening? Also, say I have 30 forms in the app, do I need to add the SqlConnection component to each form that will need to talk to the DB?
The "Main()" is a function.
And you declared a local variable "sConnection".
Your Form is another class.
A class can access only its members, global members or global static members (or some friend scenarios like C++).
Take out that declaration from "Main", either declare in the scope of your Form or declare it as a global variable, where your form can access.
Or put your connection string in a config file and read from it. (easy to configure at later point of time.)

.net load configuration in class library

let's say i have :
1) 1 WindowsForm on "A" Project
2) 1 WindowsForm on "B" Project
3) 1 class library (GAC)
Condition
Both of Project references is same
Part 1 :
I have my.settings in my class library to save configuration with public function
Part 2 :
I create value/configuration from "A" and store it in my class library.
settings has been successfully saved, and load the value/configuration with no errors
Question :
1). Why i can't load the value/configuration from "B" ? NullException shown
First I think, to use my.resources in class library but, my.resources is readonly
2). What best solution to connecting 1 class library to multiple project
code in class library to save value
Public Sub Kucing_simpan(ByVal value As String)
My.Settings.Kucing = value
My.Settings.Save()
End Sub
code in class library to load value
Public Function kucing_ambil()
Dim value As String
value = My.Settings.Kucing
Return value
End Function
code in "A"
dim save as new Zombie.Kencing 'My class Library Name
save.Kucing_simpan(textbox1.text)
code in "B"
dim load as new Zombie.Kencing 'My class Library Name
DataGridView1.Rows(0).Cells(1).Value = load.kucing_ambil
You cant do what you are trying to do - at least not the way you are going about it.
First, you have to understand how/where Settings are saved. With default naming of the app and such, project A - WindowsApplication1 will save its settings to something cryptic such as:
C:\Users\<UserName>\AppData\Local\Microsoft\_
WindowsApplication1_Url_ggn13vigzyicmtfkwaa3vi5tyxn0sy3r\1.0.0.0\user.config
NET creates the hash to make sure that apps with the same name have a different safe location to store settings. So, WindowsApplication3 will have a different hash; this is also how your 17th project with the name WindowsApplication1 doesnt accidentally load or find the settings of WinApp 1-16.
Next, your Settings Class Lib is not a separate application. As a DLL, it is operating as if it was a set of functions and such associated with the App calling it. So when Project A saves settings thru the ClassLib, they are saved to a different location than Project B. Even using a Class Lib, NET uses Application credentials and info to concoct the filename and path.
What you can do is write a Class which defines all the possible settings (or creates a List or Dictionary of them) then save to a fixed, known location such as:
Private Comp As String = "ZiggySoft"
Private Prod As String = "ZiggyWare"
Private settingsFile As String
'...
settingsfile = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
settingsfile = Path.Combine(settingsfile, Comp, Prod, "usersettings.dat")
This will result in:
"C:\Users\\AppData\Roaming\ZiggySoft\ZiggyWare\usersettings.dat"
Include the same file in each project (Add Existing Item, maybe pick Add As Link from the dropdown). Now, you can read and write your Settings to a file you are in charge of. You can save/load the entire class or List in 3-5 lines of code if you serialize it.
When Project A loads the settings, it would also get those which only apply to B or J or V, but common ones would and could be shared.

Advantages of Properties in Classes

I've been using classes for a while now, but I feel I may have been using them incorrectly.
When I create the properties for the class, I just use public variables so I end up with something like the following:
Class clsMyClass
Public Name As String
End Class
However, I've been reading some info on the net and they suggest that it should be set up in the following way:
Class clsMyClass
Private Name As String
Property UsersName() As String
Get
Return Name
End Get
Set(ByVal Value As String)
Name = Value
End Set
End Property
End Class
Is the way I'm doing it extremely incorrect? If so, why? I feel like the second method adds some sort of security but to be honest, it just looks like unnecessary code..?
One advantage of properties is that they let you customise the access to your private fields and enable you to do more so you can do the following (examples, it's not limited to that):
Make a property read-only for public access
Raise an even when a property is updated
Update other private fields when a property is updated
Validate the value that is being set
See below advantages of Properties over Variables from the C# in Depth article:
• There's more fine-grained access control with properties. Need it to be publicly gettable but really only want it set with protected access? No problem (from C# 2 onwards, at least).
• Want to break into the debugger whenever the value changes? Just add a breakpoint in the setter.
• Want to log all access? Just add logging to the getter.
• Properties are used for data binding; fields aren't.
Few other points:
1) You can also make properties read-only so no one from outside the class set the values but can fetch it.
2) You can do certain actions in the get and set. i.e. Append a prefix anytime set is called
3) You can also use auto-implemented property to minimize code like below:
Public Property Name As String
You are not doing anything wrong. Properties give you a shorthand basically, a syntactic sugar.
You can still use a backing private variable and do logic in get and set if you have to while using properties. Even better is the private/protected set or get, which is again another syntactic sugar so that you won't have to write all the code manually.
First of all, VB.NET allows you to use this syntax (called shorthand property declaration - I believe since VS 2010):
Public Property Name As String
Not so much different from this (called field declaration):
Public Name As String
Second, Microsoft data binding does not work well with fields. Try this example (see below).
Example. Put a listbox called ListBox1 (default name) and a button called Button1 on an empty form in an empty WinForms project. Replace your form code with this:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lst As New List(Of clsMyClass)
lst.Add(New clsMyClass)
ListBox1.ValueMember = "Name"
ListBox1.DisplayMember = "Name"
ListBox1.DataSource = lst
End Sub
End Class
Class clsMyClass
Public Property Name As String = "Hello"
End Class
Start the application and notice that a listbox is populated with one entry, Hello. This proves that binding worked correctly. Now replace your property declaration with a field declaration instead. Start your application one more time and notice that a listbox is showing your class type converted to String. It means that your field binding did not work, and default binding was used instead, where DisplayMember is assigned sort of classInstance.ToString().
If you are curious to learn more about what happens behind the scenes, you can put a breakpoint on .DataSource assignment, and see how DisplayMember gets reset or keeps its value depending on whether you are using fields or properties.

.net assembly does not appear in Excel's References

I'm following Rich Newman's guide to using .net code assemblies in Excel. I have made a small test class called MyPro[p in a project called MyProperty that looks like this:
Imports System.Runtime.InteropServices
Public Class MyProp
Public Function GetData() As String
Return "Hello World"
End Function
End Class
It compiles fine, puts a CLSID into regedit, and (after browsing to find the TLB) allows itself to be added to Excel's References. However, I can't actually use it. I tried this in VBA:
Private Sub test()
Dim test As New MyProperty.MyProp
MsgBox test.GetData()
End Sub
Which returns:
"Class does not support Automation or does not support the expected interface"
I assume that the error means that it can't find GetData or I'm calling it incorrectly. I have re-added the TLB, with no effect.
Any ideas?
The problem has to do with the order of operations in the bindings. You can make this work by DIMming the object then Newing it on a separate line.

How to select an image from resources via a string?

I'm coding a pokedex type deal as practice for my class.
Basically, I have a class titled "pokemon". One of the properties of the class is "ImgName" Which I want to use to display an image from the resources with the same name.
VB doesn't allow me to call the ImgName as a string and then use 'My.Resources.ImgName'
How can i do this, or what are some alternative options to it? I want it to be determined by a property in the pokemon object, and i don't want to have to hard code in an if-elseif statement for every single pokemon.
One way is you can have a resource file added to your project. Then drop the resource into it. You will be able to address it like this:
My.Resources.Resource1.ImgName
Resource1 is your resource file name, and ImgName is the resource name here. But you need to do hard code for every call. However, you get full intellisense support with type checking.
If you don't want hard code, here is a stripped down version of my production code:
Imports System.Reflection
Imports System.Xml.Linq
Public Class EmbeddedResourceManager
Private Class EmbeddedResourceManagerCore
Private Shared _executingAssembly As Assembly
Private Shared _resourcePrefix As String
Shared Sub New()
_executingAssembly = Assembly.GetExecutingAssembly
_resourcePrefix = _executingAssembly.GetName.Name & "."
End Sub
Public Shared Function GetStream(resourceRelName As String) As IO.Stream
Return _executingAssembly.GetManifestResourceStream(_resourcePrefix & resourceRelName)
End Function
End Class
Public Shared Function GetImage(ByVal resourceName As String) As Bitmap
Return New Bitmap(EmbeddedResourceManagerCore.GetStream(resourceName))
End Function
End Class
So whenever you need, just call EmbeddedResourceManager.GetImage and pass the resource name, as it appears in your project (your image file needs to be attached to a project). You need to have Build Action for an image in question to be set to Embedded Resource.
This piles up all your resource into an executable, which has both benefits and drawbacks, depending on the situation. Still, it should work for your needs, since I am assuming number of different pokemons is limited and does not change throughout the game (i.e. downloaded from a 3rd party server in real time etc.).
BackgroundImage = My.Resources.ResourceManager.GetObject(aString)
10 time easier than previous answer imho