Handling variable connection strings

Handling variable connection strings

Old forum URL: forums.lhotka.net/forums/t/1224.aspx


mikeclimbs posted on Friday, September 15, 2006

I'm using CSLA 2.1.

I have an app that will be deployed at multipe sites and users will be able to add multiple databases.  I already have a method for users to select their databases and to create connection strings based on their selections.

What is the best way to pass the connection string from the UI to the BO's.  I was thinking of setting the app.config based on there selection like the project tracker example.  Using app.config is problemmatic for development since soure control keeps setting it read only.

I'm hoping there is a better way.

Thanks,

Mike

Fabio replied on Friday, September 15, 2006

I think you can use LocalContext..
See the "change log" of 2.1..:
"Csla – ApplicationContext.LocalContext

Add a LocalContext property to Csla.ApplicationContext. LocalContext works like ClientContext and GlobalContext, but it does not get moved across the network by the data portal. This means that both the client and server have a LocalContext that is truly local to each location. LocalContext exists at the thread or HttpContext level and so is local to a user’s session on a server.

 

You can envision using LocalContext to globally transfer objects such as database connections or ADO.NET transaction objects throughout an entire data access session on a server. I’m sure other uses may be found as well, but this one is a key motivator for the addition of the functionality."

RockfordLhotka replied on Friday, September 15, 2006

Not LocalContext - that doesn't flow from client to server.

But ClientContext should work - that flows from client to server, and so is a good way to get client-side context data (like which database the user wants) to the server along with every data portal call.

kids_pro replied on Monday, December 04, 2006

Dear Rocky,

I am using Csla 2.0.3
In the login code I load some properties from the database upon successful login.
.... some code here ....
     using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) {
           if (dr.Read()) {
                  _uniqueid = dr.GetGuid("UserID");
                  _name = dr.GetString("Firstname") + ", " + dr.GetString("Lastname");

                   Csla.ApplicationContext.ClientContext["ProvGIS"] = dr.GetInt32("ProvGIS");
                   Csla.ApplicationContext.ClientContext["lang"] = dr.GetString("Lang");

.... some code here ....

I watch the value of the Csla.ApplicationContext.ClientContext["lang"] it return the value from the database - so far so good. Then I create a Utilities.cs with Language properties

namespace PID.BusinessObject {
    public static class Utilities {
        public static string Language {
            get {
                string lang;
                try {
                    lang = (string)Csla.ApplicationContext.ClientContext["lang"];
                } catch { lang = "EN"; }
                return lang;
            }
        }
    }
}

in my ContractInfo.cs
I got an exception: Object reference not set to an instance of an object.
if(Utilities.Language.Equals("EN")){
     ..... read English fields ...
}

And the stack trace:
[NullReferenceException: Object reference not set to an instance of an object.]
PID.BusinessObject.Contract.ReadOnly.ContractInfo.Fetch(SafeDataReader dr) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.BusinessObject\Contract\ReadOnly\ContractInfo.cs:180
PID.BusinessObject.Contract.ReadOnly.ContractInfo..ctor(SafeDataReader dr) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.BusinessObject\Contract\ReadOnly\ContractInfo.cs:127
PID.BusinessObject.Contract.ReadOnly.ContractInfo.GetContractInfo(SafeDataReader dr) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.BusinessObject\Contract\ReadOnly\ContractInfo.cs:120
PID.BusinessObject.Contract.ReadOnly.ContractList.DataPortal_Fetch(Criteria criteria) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.BusinessObject\Contract\ReadOnly\ContractList.cs:114

[CallMethodException: DataPortal_Fetch method call failed]
Csla.MethodCaller.CallMethod(Object obj, MethodInfo info, Object[] parameters) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\MethodCaller.cs:68
Csla.MethodCaller.CallMethod(Object obj, String method, Object[] parameters) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\MethodCaller.cs:49
Csla.Server.SimpleDataPortal.Fetch(Type objectType, Object criteria, DataPortalContext context) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\Server\SimpleDataPortal.cs:102

[DataPortalException: DataPortal.Fetch failed]
Csla.DataPortal.Fetch(Type objectType, Object criteria) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\Client\DataPortal.cs:191
Csla.DataPortal.Fetch(Object criteria) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\Client\DataPortal.cs:138
PID.BusinessObject.Contract.ReadOnly.ContractList.GetContractList(Int32 giscode, Int32 budgetyear) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.BusinessObject\Contract\ReadOnly\ContractList.cs:47
RILGP_Payment.ddlCommune_SelectedIndexChanged(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:103
RILGP_Payment.ddlDistrict_SelectedIndexChanged(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:89
RILGP_Payment.ddlProvince_SelectedIndexChanged(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:74
RILGP_Payment.ddlBYear_SelectedIndexChanged(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:59
RILGP_Payment.Page_Load(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:31
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +34
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +47
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061

But I do not get this error if I running in WinApp mode.
This only happen in WebApp and after I authenticate myself only, if I don't authenticate everything work just fine.

For your information here is my Logout() code:

        public static void Logout() {
            PIDIdentity identity = PIDIdentity.UnauthenticatedIdentity();
            PIDPrincipal principal = new PIDPrincipal(identity);

            /* set default language */
            Csla.ApplicationContext.ClientContext["lang"] = "EN";

            /* set default province */
            Csla.ApplicationContext.ClientContext["ProvGIS"] = 1000;
            Csla.ApplicationContext.User = principal;
        }
Any idea why I got this System.NullReferenceException

ajj3085 replied on Monday, December 04, 2006

You should probably upgrade to 2.1.1, because there are bug fixes from 2.0.3 to 2.1.1.

RockfordLhotka replied on Monday, December 04, 2006

You do realize that ClientContext DOES NOT get returned from server to client right? This is discussed in Chapter 4 - read the section covering GlobalContext and ClientContext for details.
 
In your description you say you watch ClientContext["lang"] get set from the database. Is this on the server? If so, that value is most certainly NOT returned to the client, and so of course you'd get a null reference exception on the client when trying to access this item.
 
Solutions:
 
You can get your values via a ReadOnlyBase-derived object and THEN set them into the ClientContext (on the client). The value will then become global to both client and server, because ClientContext flows from client to server on each call.
 
Or you can put the values into GlobalContext, and then they'll flow back and forth between client and server on every data portal call.
 
Rocky


From: kids_pro [mailto:cslanet@lhotka.net]
Sent: Monday, December 04, 2006 7:07 AM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] Handling variable connection strings

Dear Rocky,

I am using Csla 2.0.3
In the login code I load some properties from the database upon successful login.
.... some code here ....
     using (SafeDataReader dr = new SafeDataReader(cmd.ExecuteReader())) {
           if (dr.Read()) {
                  _uniqueid = dr.GetGuid("UserID");
                  _name = dr.GetString("Firstname") + ", " + dr.GetString("Lastname");

                   Csla.ApplicationContext.ClientContext["ProvGIS"] = dr.GetInt32("ProvGIS");
                   Csla.ApplicationContext.ClientContext["lang" ] = dr.GetString("Lang");

.... some code here ....

I watch the value of the Csla.ApplicationContext.ClientContext["lang"] it return the value from the database - so far so good. Then I create a Utilities.cs with Language properties

namespace PID.BusinessObject {
    public static class Utilities {
        public static string Language {
            get {
                string lang;
                try {
                    lang = (string)Csla.ApplicationContext.ClientContext["lang"];
                } catch { lang = "EN"; }
                return lang;
            }
        }
    }
}

in my ContractInfo.cs
I got an exception: Object reference not set to an instance of an object.
if(Utilities.Language.Equals("EN")){
     ..... read English fields ...
}

And the stack trace:
[NullReferenceException: Object reference not set to an instance of an object.]
PID.BusinessObject.Contract.ReadOnly.ContractInfo.Fetch(SafeDataReader dr) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.BusinessObject\Contract\ReadOnly\ContractInfo.cs:180
PID.BusinessObject.Contract.ReadOnly.ContractInfo..ctor(SafeDataReader dr) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.Busi nessObject\Contract\ReadOnly\ContractInfo.cs:127
PID.BusinessObject.Contract.ReadOnly.ContractInfo.GetContractInfo(SafeDataReader dr) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.BusinessObject\Contract\ReadOnly\ContractInfo.cs:120
PID.BusinessObject.Contract.ReadOnly.ContractList.DataPortal_Fetch(Criteria criteria) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.BusinessObject\Contract\ReadOnly\ContractList.cs:114

[CallMethodException: DataPortal_Fetch method call failed]
Csla.MethodCaller.CallMethod(Object obj, MethodInfo info, Object[] parameters) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\MethodCaller.cs:68
Csla.MethodCaller.CallMethod(Object obj, String method, Object[] parameters) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\MethodCaller.cs:49
Csla.Server.SimpleDataPortal.Fetch(Type objectType, Object criteria, DataPortalContext context) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\Server\SimpleDataPortal.cs: 102

[DataPortalException: DataPortal.Fetch failed]
Csla.DataPortal.Fetch(Type objectType, Object criteria) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\Client\DataPortal.cs:191
Csla.DataPortal.Fetch(Object criteria) in D:\CSLA.NET 2.0.3\csla20cs\Csla\DataPortal\Client\DataPortal.cs:138
PID.BusinessObject.Contract.ReadOnly.ContractList.GetContractList(Int32 giscode, Int32 budgetyear) in D:\Documents\Visual Studio 2005\Projects\PID2007\PID.BusinessObject\Contract\ReadOnly\ContractList.cs:47
RILGP_Payment.ddlCommune_SelectedIndexChanged(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:103
RILGP_Payment.ddlDistrict_SelectedIndexChanged(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:89
RILGP_Payment.ddlProvince_SelectedIndexChanged(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:7 4
RILGP_Payment.ddlBYear_SelectedIndexChanged(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:59
RILGP_Payment.Page_Load(Object sender, EventArgs e) in d:\Documents\Visual Studio 2005\WebSites\PIDWeb\RILGP\Payment.aspx.cs:31
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +34
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +47
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061

But I do not get this error if I running in WinApp mode.
This only happen in WebApp and after I authenticate myself only, if I don't authenticate everything work just fine.

For your information here is my Logout() code:

   &n bsp;    public static void Logout() {
            PIDIdentity identity = PIDIdentity.UnauthenticatedIdentity();
            PIDPrincipal principal = new PIDPrincipal(identity);

            /* set default language */
            Csla.ApplicationContext.ClientContext["lang"] = "EN";

            /* set default province */
            Csla.ApplicationContext.ClientContext["ProvGIS"] = 1000;
            Csla.ApplicationContext.User = principal;
        }
Any idea why I got this System.NullReferenceException



kids_pro replied on Monday, December 04, 2006

Dear Rocky,

Yes, after review the chapter I realized that I should use GlobalContext.
However after login even GlobalContext become null reference even I set it value in the PIDIDentity.cs
To make it works I need to reset it value in Global.asa

        if (principal == null) {
            PID.BusinessObject.Security.PIDPrincipal.Logout();
        } else {
            Csla.ApplicationContext.User = principal;
            Csla.ApplicationContext.GlobalContext["Language"] = "KH";
        }

mikeclimbs replied on Friday, September 15, 2006

Thanks,

I'll take a look and let you know my results.

Mike

Copyright (c) Marimer LLC