Correct way to handle Caching of DB-Data - c#

I always wondered how exactly you'd handle caching of database-values (in C#, ASP.NET) so you e.g. don't reload several DataSource-Bound ASP-Controls or don't have to reload them everytime you use a certain backend method.
Let's just take the following example:
aspx.cs-File:
List<FormElement> elements = FormElement.GetForForm(Session["FormName"].ToString());
Backend-Method:
public static List<FormElement> GetForForm(string fName)
{
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand("select Rank, Control, Variable from inspire.dbo.formelement where formid=(select id from inspire.dbo.form where name=#name)", Database.Conn);
cmd.Parameters.Add(new SqlParameter("#name", fName));
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
return dt.Rows.ToList<FormElement>(item => new FormElement(item));}
How exactly would I handle caching here?
Thanks,
Dennis

what we have done for the caching:
in page side, use a global container (eg. dataset) to store all the required data, each data add a time flag for it
in backend side, use a same container to store the data, and also with the time flag
when page refresh, compare the time flag with current datetime, get data from that container;
or send a refresh_fetch to backend side, backend will get data from db and update caching content for its container, then send back the updated data to page
page update its container and display out
the flow is simply like this, however, based on real situation, the container, the refresh strategy... maybe different

Related

How to loop through multiple connection strings in a db and query them?

I don't know how to loop through my local database and add the values to this string:
string credentials = #"server = 127.0.0.1;
user id = system;
port = 3308;
Password = 975315";
https://i.imgur.com/6B4YFw7.png
I kind of need something like this:
string credentials = #"server = IDindb;
user id = IDindb;
port = Portindb;
Password = Pwindb";
foreach(rowofdata in localdb)
{
MySqlConnection con = new MySqlConnection(credentials);
con.Open(); //Opens the connection
MySqlCommand cmd = new MySqlCommand(sqlQuery, con); //Sends the
query to "show slave status"
Create a new table in browser that shows if server is running or not.
}
This is quite a good homework assignment - It touches frontend, database, networking and middleware, and importantly it forces you to properly think through all the little decisions of what might go wrong, e.g.
what do you do when the server doesn't respond (write "server down
into your html table)
how do you trap this without your own code failing.
What if the servers take a really long time to respond? Timeout?
Should you be doing this to each server in succession, or
all at once, adding their responses into the table as you go?
What I'm saying is you should think about your overall solution some more before diving into the code.
To answer the question, assuming you have some code to connect to the local db and query the table, rowofdata will be a recordset, with each row populated per the row in your image.
Extract the server, user, password etc credentials from it:
var masterHost = rowofdata["Master_Host"].ToString();
and create the connection string inside the for-loop.
var credentials = $"server={masterHost};user id={userId}; port={portId}; Password={password}";
The Create new Table in browser part will depend on which platform/language you're writing in. And in any case shouldn't be done here, unless you're intent on mixing db access with html (#Razor? classic asp?).
Store the server / status values in a list (of server object, with status etc), then subsequently use them to populate the html.
(Or build the html table and render that, and use ajax to request the status of each).
(unrelated - how do you plan on implementing the stop/start/fix button code?)

gridview With delete action .column needs to be updated

I have a gridview with delete action.. particular row needs to be updated on it. I am getting errors when doing that.
Invalid postback or callback argument. Event validation is enabled
using in configuration or <%#
Page EnableEventValidation="true" %> in a page. For security
purposes, this feature verifies that arguments to postback or callback
events originate from the server control that originally rendered
them. If the data is valid and expected, use the
ClientScriptManager.RegisterForEventValidation method in order to
register the postback or callback data for validation.
How to write client side event for the gridview.
my gridview
please tel me how to rectify this errors..
requirement is to on clicking delete button, that row needs to be updated
to particular set values..
You are doing a wrong call to AddWithValue method. You are specifying a SqlDbType when AddWithValue is supposed to do it implicitly:
string yourId = "1";
con.Open();
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Id", yourId);
Also, I donĀ“t see where you have the value Id that is supposed to be passed as parameter. I added yourId variable since there is not id value.
If you want to specify the type, dont use AddWithValue, use Add, instead:
string yourId = "1";
con.Open();
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#Id", SqlDbType.NVarChar).Value = yourId;
Also, are you sure that ID column should be NVarChar??
private void Page_Load()
{
if (!IsPostBack)
{
//Bind Date
}
}
alterantively you can
EnableEventValidation="false"
but that is not recommended

Use data from DataTable in all forms

In the class I execute a stored procedure and return a DataTable.
public DataTable getUserInfo(int abid)
{
DataTable tbl = new DataTable();
string constring =ConfigurationManager.ConnectionStrings["myconn"].ConnectionString;
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("getUserInfo", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#ABID", abid);
SqlDataAdapter adap = new SqlDataAdapter(cmd);
adap.Fill(tbl);
}
}
return tbl;
}
Then in the code behind of the default.aspx.cs page I call the class and using a foreach loop I get all the data I need.
DataTable tbl = new DataTable();
tbl = u.getUserInfo(abid);
foreach (DataRow row in tbl.Rows)
{
string firstName = row["firstName"].ToString();
string lastName = row["lastName"].ToString();
string fullname = row["fullname"].ToString();
string Phone = row["phone"].ToString();
}
This solution works if I only had to use the data in this page only. I need the same data to use in different pages in the project. Of course, I could call the class every time and create different data tables and store them in different variables, but I know it's not very efficient. I'm sure there's a better way to do this.
Is there a way that I could create global variables? For instances I load the datatable into those variables and I can use them throughout the project? Or any other solution?
Thanks
If that data is shared among different users then use Cache object. See: ASP.NET Caching: Techniques and Best Practices.
But if that data is unique to each user then store that information in a Session object. But remember, Sessions are maintained for each user on Server, If you keep too much data in Session then it will require more resources from the Server.
See: ASP.NET Session State Overview
To store information in Session
//To store
Session["UserInfo"] = tbl;
To retrieve
DataTable tbl = Session["UserInfo"] as DataTable;
if (tbl != null)
{
//Datatable found;
}
Session object can be accessed on multiple pages.
You also have other options to maintain state across pages in ASP.Net, like Cookies. See
ASP.NET State Management Overview
Web is stateless, which means a new instance of a web page class is re-created each time the page is posted to the server. As we all know, HTTP is a stateless protocol, it can't hold client information on a page.
If the user inserts some information and move to the next page, that data will be lost and the user would not be able to retrieve that information. We need to store information. Session provides a facility to store information on server memory. It can support any type of object to store along with our own custom objects. For every client, session data is stored separately, which means session data is stored on a per client basis. Have a look at the following diagram:
State management using session is one of the best ASP.NET features, because it is secure, transparent from users, and we can store any kind of object in it.
Advantages:
It helps maintain user state and data all over the application.
It is easy to implement and we can store any kind of object.
Stores client data separately.
Session is secure and transparent from the user.
Disadvantages:
Performance overhead in case of large volumes of data/user, because session data is stored in server memory.
Overhead involved in serializing and de-serializing session data, because in the case of StateServer and SQLServer session modes, we need to serialize the objects before storing them.
Reference:
1.http://www.codeproject.com/Articles/32545/Exploring-Session-in-ASP-Net
I suggest that you implement a lazy-loading solution to this.
Since static member are shared across all requests to the application, you can cache data that you know isn't going to change. Obviously you have to be careful about caching too much or for too long, or you're going to run int RAM issues. You'll also have to consider concurrency.
Here's a simplified example: create a class that represents a user, and then create a static method, LoadByID(int id), and a static Dictionary to stored already-loaded users. Then, when a page requests a user, serve them the item from the cache if it already exists.
//... user instance fields ...
private static Dictionary<int, User> cache = new Dictionary<int, User>();
private static object lockObj = new object();
public static User LoadByID(int id)
{
lock (lockObj) //Prevent double-adding items
{
if (cache.ContainsKey(id))
{
return cache[id]; //We've already loaded the record.
}
else
{
//Some function that actually calls the database
//and constructs user objects
User loaded = LoadUserInternal(id);
cache.Add(id, loaded)
return loaded;
}
}
}
private static User LoadUserInternal(int id)
{
//Load and construct the user
}

Send data from one page to another

I am trying to send form data from one page to another using C# ASP.Net. I have two pages default.aspx and default2.aspx.Here is the code I have in default.aspx:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Go"
PostBackUrl="~/Default2.aspx" />
<br />
From what I know so far the PostBackUrl is used to set the page in which you want the data to be sent is this correct?
Also how can I retrieve the data that is sent to Default2.aspx?
You have a few options, consider
Session state
Query string
Session state
If you are going to send data between pages, you could consider the use of Session State.
ASP.NET session state enables you to store and retrieve values for a
user as the user navigates ASP.NET pages in a Web application. HTTP is
a stateless protocol. This means that a Web server treats each HTTP
request for a page as an independent request. The server retains no
knowledge of variable values that were used during previous requests.
ASP.NET session state identifies requests from the same browser during
a limited time window as a session, and provides a way to persist
variable values for the duration of that session. By default, ASP.NET
session state is enabled for all ASP.NET applications.
Best of all, it is easy!
Put data in (for example on default1.aspx)
Session["FirstName"] = FirstNameTextBox.Text;
Session["LastName"] = LastNameTextBox.Text;
Get it out (for example on default2.aspx)
string firstname = Session["FirstName"] // value of FirstNameTextBox.Text;
string lastname = Session["LastName"] // value of LastNameTextBox.Text;
Query string
If you are sending small amounts of data (eg id=4), it may be more practical to use query string variables.
You should explore the use of the query string variables, e.g.
http://www.domain.com?param1=data1&param2=data2
You can then get the data out like
string param1 = Request.QueryString["param1"]; // value will be data1
string param2 = Request.QueryString["param2"]; // value will be data2
You can use something like How do you test your Request.QueryString[] variables? to get the data out.
If you are unfamiliar with querystring variables check out their wikipedia article
Session variables can be useful in this context.
Foe example suppose your textboxes contain login credentials, then save them in sessions so that you can later use them in any other page. Like this:
In Button_Click-
Session["name"]=TextBox1.Text;
Session["pwd"]= TextBox2.Text;
Instead of PostBackUrl="~/Default2.aspx" you can write the following-
//in button click
Server.Transfer("~/Default2.aspx");
In Default2.aspx page load:
string a= Session["name"].ToString();
string b= Session["pwd"].ToString();
Try this in the Page_Load of Default2.aspx.
if (PreviousPage != null)
{
if (((TextBox)PreviousPage.FindControl("TextBox1")) != null)
{
string txtBox1 = ((TextBox)PreviousPage.FindControl("TextBox1")).Text;
Response.Write(txtBox1);
}
}
And yes you are correct, the data from page 1 will be sent to page 2 if you use the PostBackUrl attribute.
MSDN link
While all the answers here will work some aren't the most efficient. Why would a simple/standard http POST have to invoke (expensive) server-side Sessions?
Your code isn't doing anything special - it is simply POSTing a form to another page. All you need to do to obtain the POSTed data is go through the Request.Form collection.
Prior to the availability to set the PostBackUrl (if memory serves version 1 of asp.net), Server.Transfer and getting references to the previous page was how cross-page POSTing was done/documented. However, with PostBackUrl, things go back to basics, the way it should be - a standard http POST from one resource to another.
Here's a similar SO thread that maybe helpful.
another way is to save the data on a database and fetch it back on the other page:
//update
string query = "UPDATE table SET col = 'a'";
SqlCommand command = new SqlCommand(query, connection);
command.ExecuteScalar();
//select
string query = "SELECT col FROM table";
SqlCommand command = new SqlCommand(query, connection);
string value = command.ExecuteScalar();

Load data from database in _layout.cshtml

I am creating a web application using ASP.NET MVC 4.
I want to display the user's nickname on all of pages, so I have to load it in _layout.cshtml.
Please note that I'm storing user's nickname manually. (In my own database and my own tables.)
I can add user's User name by Membership.GetUser().UserName, but I want to load his nickname from database and show it in _layout.cshtml.
How to do that?
Let me give a simple solution for what you want:
write an action in a controller (mine is CommonController):
public ActionResult NickName()
{
SqlConnection cn = new SqlConnection(cnstr);
SqlCommand cmd = new SqlCommand(cmdStr, cn);
cn.Open();
SqlDataReader dr = cmd.ExecuteReader();
string nickName = string.Empty;
while (dr.Read())
{
nickName = dr["nick_Name"].ToString();
}
dr.close()
return Content(nickName);
}
put the below line in everywhere you want in _Layout:
nickname = #{Html.RenderAction("NickName", "Common");}
Finished!
Thanks to #SergRogovtsev for recommending:
nickname = #Html.Action("NickName", "Common")
first asked:
Are you using entity framework?
You can use partial views in _Layout either using EF or ADO.
If you mean you can't access aspnet_membership table by using entity framework, you should ask your question in another way!
let me know more about your problem by giving some sample of your code.
I would advise you to upon logging in, store the username in a session variable (which is done by accessing the Session object, which implements a key=value pair architecture allowing you to store and retrieve your data at will). It's a drag on performance to have to make a database call for EVERY page that loads, and a single nickname string variable in session won't take up that much space on your server.
As far as loading the variable you could use the code posted by Vahid, but I would recommend you if your site is still in its infancy to take the extra time to learn and implement Entity Framework. It is cleaner, easier and Microsoft is really pushing data connection management in that direction.
I have used a combination of Mr_Creostoe and Vahid answers.
I am saving nickname in a session (as Mr_Cresotoe said), and if there isn't such session (for example, if user ticked remember me checkbox and is visiting after many time), I'll create that session using RenderAction. (As Vahid said).
Thank you guys!

Categories