In my website there are dozens of calls made to a sql database and each time it passes along the ID of the user requesting data. I'm attempting to set up a singleton class that will only need to make one call to the database to grab the person's ID along with other user attributes that only need to be grabbed once.
I thought I had everything set up properly and it seemed to be working so I moved the code change into production and have gotten calls from several users saying when they log in, they are all being identified as me. This is based on the welcome message at the top of my home page that says "Welcome ", and everybody's userName is showing as me.
My singleton is below. After getting the call I started debugging, what I have found is that the formValues() method where I thought the values are being set is never getting called. The only thing that does get called is the public Instance method. I'm guessing that's obvious to everybody that knows what they are doing :).
I don't think this is relevant, but the instance of the variables is being called in my code like: formValues.Instance.firstName.
So how close am I? Is this thing salvageable?
public sealed class formValues : System.Web.Services.WebService
{
static readonly formValues instance = new formValues();
public string userName;
public string firstName;
public string personID;
public string secBlur;
public int admin;
public int fafsa;
public int staff;
static formValues()
{
}
formValues()
{
//This retrieves the person logged into windows/active directory
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
userName = id.Name;
// Grab this user's firstname, personID, and Admin status
string mySQL = "exec get_userData #userName";
string cf = System.Configuration.ConfigurationManager.ConnectionStrings["DistrictAssessmentDWConnectionString"].ConnectionString;
SqlConnection connection = new SqlConnection(cf);
SqlCommand command = new SqlCommand(mySQL, connection);
command.Parameters.AddWithValue("#userName", userName);
connection.Open();
SqlDataReader dr = command.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
personID = dr["personID"].ToString();
firstName = dr["firstName"].ToString();
admin = Convert.ToInt32(dr["admin"]);
secBlur = dr["secBlur"].ToString();
fafsa = Convert.ToInt32(dr["FAFSA"]);
staff = Convert.ToInt32(dr["staffSec"]);
}
}
connection.Close();
}
public static formValues Instance
{
get
{
return instance;
}
}
}
The problem is that these properties (fields, actually) are in a singleton:
public string userName;
public string firstName;
public string personID;
public string secBlur;
public int admin;
public int fafsa;
public int staff;
...along with the fact that they get populated in the constructor. That means the first time you create the class, it gets populated. If you re-use that same class instance as a singleton, the constructor will never get called again, which means that the values populated will be set once and remain forever.
In other words, your user data is a singleton. Unless you will only have one user ever, that's not good.
First, I would separate the class that retrieves the data from the class that contains the data.
The data might look like this:
public class UserData
{
public string UserName { get; set; }
public string FirstName { get; set; }
// ..etc...
}
That model contains the data. It does not contain the code to populate the data.
Then, create a class that retrieves the data. It shouldn't retrieve the data in the constructor. The constructor is for creating the class. It's not where we would put the stuff that the class actually does.
That class might have a method like this:
public UserData GetUserData()
...which would create an instance of UserData and return it.
For what it's worth, for most scenarios we don't need to create a singleton.
Suppose you have this class:
public class SqlUserDataProvider
{
UserData GetUserData()
{
...
}
}
If the constructor doesn't do anything "heavy" like read data or files, you could just create a new instance each time you need one. It's less efficient than using a single instance, but the difference is usually so minutely trivial that it's not worth considering.
Or, you can create a single instance and re-use it. In that case you're using it as a singleton, but technically it isn't one. A singleton is class written so that it is only possible to create a single instance of it. Most of the time there's just no reason to do that. It's extra lines of code to strictly enforce a restriction on how we use the class. It can potentially make code less maintainable and harder to debug. So it's extra work for either no benefit or negative benefit.
Basically, you want to do a cache. For http requests you need to check if value is already in cache, if it is not - read from the database, otherwise use cache.
You can start with built-in Cache
As for singletons, simplest solution is to implement them using Lazy. Here is good article
The instance object is created just once on an application lifetime.
So your private constructor formValues(), where you get the FormsIdentity, is actually executed just once after application starts up first time ever.
After that , for all incoming requests, the already populated instance is given out.
That's why you see the same username, for any further requests.
Since the requirement is per-user basis, and not something global across application, "singleton" probably wont help. Thanks.
Related
I am having some issues understanding how I can assign dynamic values from another class into other variables - I have tried using the correct namespaces, correct syntax and reading up on the documentation that the error provides - however no luck even when trying to implement examples shown. I have very little knowledge in regards to C# as I am mainly doing front end, however have to step up and start picking up some Back end oriented things at the company I work at
The current code I have is as follows:
BrazeConnectionInputs.cs
namespace Workflow.Connector.Braze.Models
{
public class BrazeConnectionInputs
{
public string Username { get; set; }
public string Password { get; set; }
}
}
CreateCampaign.cs
public class CreateCampaignRunner
{
private const string Username = BrazeConnectionInputs.Username; // BrazeConnectionInputs.Username errors
private const string Password = BrazeConnectionInputs.Password; // BrazeConnectionInputs.Username errors
}
You need to learn about objects vs classes. You should have an instance of the source class (BrazeConnectionInputs) that might be called something like model.
You can then explicitly assign across by creating a new instance of CreateCampaignRunner like var runner = new CreateCampaignRunner() and then assign the values in a number of ways:
Explicitly like runner.UserName = model.UserName
By using an explicit constructor var runner = new CreateCampaignRunner(model)
Object initializer syntax
Other ways are available
Highly recommend you do a basic C# course
This is actually 2 questions in one.
I have an asp.net mvc application where I have to load a list of Modules, its just a simple list with ID, modulename and a class name to render it on the view with font awesome.
My model is like this:
public class Module
{
[Key]
public int Id { get; set; }
public string ModuleName { get; set; }
public string FontAwesomeClass { get; set; }
}
Because the module list is a Partial View that will render some icons on the top navigation bar, I dont want that for each refresh of the app, it goes to the DB, so it must be cached(I am using Azure REDIS Cache, not relevant for the question anyway), so instead of calling the DB context directly from the controller, I am calling a Cache Class that will check if the cache object exists, if not it will retrieve it from DB, if it does, it will return it from cache.
This my solution structure:
http://screencast.com/t/uayPYiHaPCav
Here is my controller Module.cs
public ActionResult GetModules()
{
return View(Cache.Module.GetModules());
}
As you can see the Controller does not have any logic where to get the data from.
Here is the Module.cs (on the Cache Namespace)
public class Module
{
private AppDataContext dbApp = new AppDataContext();
//Load modules from cache or from database
public static List<Models.Module> GetModules()
{
IDatabase cache = Helper.Connection.GetDatabase();
List<Models.Module> listOfModules = (List<Models.Module>)cache.Get("Modules");
if (listOfModules == null)
{
return dbApp.ModuleList.ToList();
}
else
{
return listOfModules;
}
}
}
Here I have a compiler error which I am not sure how to best fix it:
Error CS0120 An object reference is required for the non-static field,
method, or property 'Module.dbApp'
So that was my first question.
The 2nd question is more about the design pattern, do you consider this correct or not? the way I am trying to get the data from Cache, and its actually the Cache class which checks if data is on it or if it has to go to the DB.
First Question: make your private member static
private static AppDataContext dbApp = new AppDataContext();
2nd Question: your cache strategy seems pretty standard. The only thing is that you might want to expire cache data. For example, the cached data can get old and the longer it stays in the cache the older it gets. You might at some point want to expire it and get fresh data again.
Update:
#EstebanV for code sample (this off the top of my head, don't assume that it compiles):
/**
ICachedPersonDao abstracts away the caching mechanism
away from the core of your application
**/
public CachedPersonDao : ICachedPersonDao
{
private IPersonDao personDao = null;
public CachedPersonDao(IPersonDao personDao)
{
this.personDao = personDao;
}
public Person GetPersonById(int id){
bool isInCache = CACHE.SomeFunctionThatChecksInYourCache(id);
if (isInCache)
{
return CACHE.SomeFunctionThatReturnsTheCachedPerson(id);
}
else
{
//Well it's not in the cache so let's get it from the DB.
return this.personDao.GetPersonById(id);
}
}
}
/**
IPersonDao abstracts database communication
away from the core of your application
**/
public class PersonDao : IPersonDao
{
public Person GetPersonById(int id)
{
/** Get the person by id from the DB
through EntityFramework or whatever
**/
}
}
Usage:
In your controller, use ICachedPersonDao if you want to attempt to get from cache or use IPersonDao if you want to get it directly from the database without checking the cache.
Like I said, you should learn Dependency Injection it will help "inject" these dependencies into the classes that uses them.
I say again, this is off the top of my head. It won't compile. It's just to illustrate the concept.
I am developing an ASP.NET MVC 4 application. userMenus is a static variable that is loaded every time a user logs in.
public class MenuCL
{
public static List<UserMenu> userMenus = new List<UserMenu>(); // the static variable
}
public class UserMenu
{
public decimal MenuID { get; set; }
public string MenuName { get; set; }
public string Controller { get; set; }
public bool Permission { get; set; }
}
I use that static variable to check whether or not the logged in user has permission to a menu/controller in a custom authorize filter.
It works fine when a single user is logged in, but when two or more users are logged-in, it's all messed up, I mean the error page("you don't have access to this page") is displayed to a user that has permission to the menu/controller.
Only now I realized it's the static variable that is causing all the trouble, after I read this :
The static variables will be shared between requests. Moreover they will be initialized when application starts, so if the AppDomain, thus application gets restarted, their values will be reinitialized.
So I need a replacement for this static variable. Anyone has any suggestion?
You can still use a static field which is a property that provides access to a session variable.
public static List<UserMenu> UserMenus
{
set
{
Session["UserMenus"] = value;
}
get
{
return Session["UserMenus"] == null ? new List<UserMenu>() : (List<UserMenu>) Session["UserMenus"];
}
}
In order to get this working on a web farm which uses a session state server (or sql server), you need to put [Serializable] attribute on top of UserMenu.
I don't think, this way you need to modify your code very much.
My question is, why do you want to use static variable? Do you want to share the values across the application? In this case you can better use session.
Updated
Assume lst as a non static List of UserMenu. Then you can use the following method to store it in session and get it bak whenever you want.
To store
Session["usemenulist"] = lst;
To get it back
try
{
lst = (List<UserMenu>)Session["usemenulist"];
}
catch
{
}
Note
If you are getting the values from the database lo load it to the List for the first time, then you can query database to get it from the database whenever you want, instead of storing it in the session. (This is another option apart from Session, you may try this way also if you want.)
I am a complete newbie to Powershell development and I am trying to write a Powershell Cmdlet in C# that will be used as an interface to a REST API.
I would like to have some kind of setup Cmdlet where the user will be prompted for an Uri, username and password to the REST API and then call Cmldlets like Get-Item without having to enter those parameters. Pretty much like the Azure provider for Powershell works where you can set the current subscription by calling Select-AzureSubscription and then call Save-AzureVhd without having to enter the subscription name again.
What is best practices for keeping state between calls to different Cmdlets?
EDIT:
I am not sure that this is the best way to solve it but what I did is that i added a singleton class that holds the state.
I have one Cmdlet, Select-Project -Name MyProject that sets a public property in my singleton class and then my other Cmdlets can access that property.
If they're running V3 or better, you could have the setup set those values in $PSDefaultParameterValues.
See:
get-help about_parameters_default_values
for details on setting values.
You're looking for PSCmdlet.SessionState.
I solved this same problem by creating a small bridge class, MyCmdlet that all my own cmdlets derive from, and it contains helpers that manage the session state, along with the definition of the object that holds the things you want to persist. In this case I'll just make up some simple things like a username and a database name.
// In MyCmdlet.cs
public class MyStateInfo {
public string Username { get; set;}
public string DbName { get; set;}
}
protected abstract class MyCmdlet : PSCmdlet {
private const string StateName = "_Blah";
protected MyStateInfo getState()
{
if ( ! SessionState.PSVariable.GetValue(StateName, null) is MyStateInfo s))
SessionState.PSVariable.Set(StateName, s = new MyStateInfo());
return s;
}
}
At this point all your cmdlets should inherit from MyCmdlet, and getState() will always return an existing or new variable: changes to the class persist in that same session.
There are probably lots of ways to integrate this in your overall cmdlet parameter design, and this is still kinda new to me so I'm not sure if it's a best practice, but I've solved it by creating a helper cmdlet to set the initial values:
[Cmdlet(VerbsCommon.Set, "MyUsername")]
public class Set_MyUsername : MyCmdlet {
[Parameter(Mandatory = true, Position = 1)]
public string Username {get; set; }
protected override void ProcessRecord()
{
base.ProcessRecord();
WriteVerbose($"Saving {Username} in session state");
getState().Username = Username;
}
}
Then some later cmdlet needs to do something with that:
[Cmdlet(VerbsCommunication.Connect, "Database")]
public class Connect_Database : MyCmdlet {
[Parameter(Mandatory = false)]
public string Username { get; set; }
// other parameters here
protected override void BeginProcessing()
{
base.BeginProcessing();
if (Username == null)
Username = getState().Username;
if (Username == null)
{ // ERROR HERE: missing username }
}
// more stuff
}
Then, your Connect-Database will take an explicit -Username steve parameter (not consulting or touching session state), but without that parameter it pulls it from your session state object. If the username is still missing after this, it fails (probably by ThrowTerminatingError).
Your Select-Project could work the same way.
I usually provide a Get-MyState cmdlet that just writes the state object to the pipeline output, mainly for debugging. You're not limited to just one variable if your application warrants separating these things.
Maybe something like powershell's CimSession support? You use new-cimsession to create a session (which contains state) and then pass the cimsession object to various other cmdlets. This wouldn't work with get-item as mentioned in the OP though.
However the EDIT in the OP describes an implementation that would be unlikely to work with get-item (if I understand correctly).
If support by get-item was really a requirement then I believe a PS provider (as in get-PSProvider) would be the way to go. PS Providers will work with cmdlets like get-item and can hold state via PSDrives (as in get-PSDrive).
struggling To achieve a solution for a basic Task:
working with more than one Sql Data table, as a source, for a WebSite application...
that's what leads me here once again... seeking for an Experienced C# .net Developers Help.
i was just trying to add some basic logic for a proper implementation,Like using
a dedicated namespace & classes, To Hold reference for All DATABASE tables,
(before i try working / learning about Entities Framework approach.)
i would like to try implement same of basic features of EF ...by my self, and that way... i will also learn how to properly work with classes.
as it is so far ... structured : with my little knowledge
a 'helper'.. namespace , say the company name is: HT technologies
so I've named the namespace HT_DbSchema ...that contains :
tables names
public sealed class HTDB_Tables
{
public const string Customers= "Customers";
public const string Times= "Times";
}
tables IDs
public sealed class HT_tblIDs
{
public const int tblCustomersID = 1, tblTimesID = 2;
}
tables Columns Lists ...(just one example)
public class HTDB_Cols
{
public class tblCustomers
{
public const string CustId = "custId",
CustName = "custName",
CellPhone = "cellPhone" .... etc'
}
}
and as all those 3 classes are serving all projects ..
there's another helper class for constructor Per Table For the Current Project
public class DBMetaDetails
{
public struct DbTable
{
public string TableName { get; set; }
public int TableID { get; set; }
}
}
so still these are all construction / helpers Classes and are separated from the project,
now for current project
What is The Appropriate way to get it done, using above Classes and constructor within a project
(i could name those templates)
what i was doing so far to implement some order is :
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
.... some other App inits here
}
else
{
}
// this method should be the one that instanciates the DbTable struct
//and set the values of tables name and "ID"
setTablesReferences();
}
And Here's where the confusion starts :
in a day by day usage i want to try implement it in a WebSite application :
public void setTableReferences()
{
DBMetaDetails.DbTable CustMeta = new DBMetaDetails.DbTable();
DBMetaDetails.DbTable TimesMeta = new DBMetaDetails.DbTable();
}
so now i need to set CustMeta & TimesMeta details(ids & names)
the struct has a kind of a template structure a kind'a systematic technique to initialize and assign values, so it brings some decent order to my logic with it's existence .
so what is the confusing part ?
from one point of view(safety), i need those tables detailes to be readonly
so DbTable.TableID, and DbTable.TableName would not get overWriten by mistake.
having said that, there should be only one place it could be SET ... a dedicated section of the application, like setTableReferences() above,... there i might add :
CustMeta.TableID = HT_tblIDs.tblCustomersID
CustMeta.TableName = HTDB_Tables.Customers;
on the other hand, i need the information of the tables to be Accessible,
so if let's say i would like to add those DataTables into a DataSet
DataSet ALLTablesSet = new DataSet();
// assuming the SQL actions already been taken in another method previosly...
// so DataTable is already retrived from DB
//...but only as a short usage example:
AllTablesSet.Tables.Add(new DataTable(CustMeta.TableName));
My Question is What is the Correct Way to work with structs ... as in My Scenario,
So in one section of app: you would initialize - assign it with a value privately.
and from other sections of the app you could use its value (Only For Readings)
so that way, the application will not be able to access it's value for writing,
only by reading values, i think it should be trough another (Public ReadOnly) Variable.
so that variable was meant to be exposed ...and it's value could not be "harmed"
If I understand the question correctly, the way I would prevent other code from modifying it is by removing the setters on the properties. However, you still need to set them at some point, so rather than removing the setters completely, you can just make them private. For example:
public string TableName { get; private set; }
If you do this, the only place you can set this data is within the struct itself, so you would need to create a constructor that took the initial values you wanted. So something like:
public struct DbTable
{
public DbTable(string tableName, int tableId)
{
this.TableName = tableName;
this.TableID = tableId;
}
public string TableName { get; private set; }
public int TableID { get; private set; }
}